From a734dfc02df72ed79e1e4082829876e459f36d5f Mon Sep 17 00:00:00 2001 From: Levironexe Date: Sat, 26 Oct 2024 19:45:08 +0700 Subject: [PATCH] Update overview and vulnerabilities section with proper data fetching method --- app/api/backend.mjs | 684 ++++--- .../ActivityPool-1729788732008-144976194.sol | 1648 ----------------- .../ActivityPool-1729789040141-363580194.sol | 1648 ----------------- .../ActivityPool-1729789161739-111170816.sol | 1648 ----------------- .../ActivityPool-1729789209485-72963277.sol | 1648 ----------------- .../ActivityPool-1729789257596-770519629.sol | 1648 ----------------- .../ActivityPool-1729789540985-915752235.sol | 1648 ----------------- .../ActivityPool-1729791081574-279065936.sol | 1648 ----------------- .../ActivityPool-1729807762472-693738646.sol | 1648 ----------------- .../ActivityPool-1729808024413-309876997.sol | 1648 ----------------- .../ActivityPool-1729808113420-601666536.sol | 1648 ----------------- .../ActivityPool-1729808507370-473274218.sol | 1648 ----------------- .../ActivityPool-1729808603511-614676959.sol | 1648 ----------------- .../ActivityPool-1729820423782-940160024.sol | 1648 ----------------- .../ActivityPool-1729820471994-34420655.sol | 1648 ----------------- .../ActivityPool-1729820576582-824190408.sol | 1648 ----------------- .../ActivityPool-1729821244300-939222585.sol | 1648 ----------------- .../ActivityPool-1729821496223-688339861.sol | 1648 ----------------- .../ActivityPool-1729821817840-171758606.sol | 1648 ----------------- .../ActivityPool-1729821940759-282179510.sol | 1648 ----------------- .../ActivityPool-1729821993926-279009626.sol | 1648 ----------------- .../ActivityPool-1729822490209-444268394.sol | 1648 ----------------- .../ActivityPool-1729823113167-316818505.sol | 1648 ----------------- .../ActivityPool-1729823400774-680295923.sol | 1648 ----------------- .../ActivityPool-1729823724402-583299337.sol | 1648 ----------------- .../ActivityPool-1729824294573-151604978.sol | 1648 ----------------- .../ActivityPool-1729824388248-854683049.sol | 1648 ----------------- .../ActivityPool-1729824663495-208623935.sol | 1648 ----------------- .../ActivityPool-1729824691606-708783209.sol | 1648 ----------------- .../ActivityPool-1729824763048-505946666.sol | 1648 ----------------- .../Test_1-1729808659268-441728940.sol | 143 -- components/button/upload-form.tsx | 4 +- .../section/contract-scan-result-section.tsx | 322 ++-- components/section/overview.tsx | 39 +- components/section/result-body.tsx | 28 +- components/section/vulnerability.tsx | 160 +- 36 files changed, 669 insertions(+), 48503 deletions(-) delete mode 100644 app/api/uploads/ActivityPool-1729788732008-144976194.sol delete mode 100644 app/api/uploads/ActivityPool-1729789040141-363580194.sol delete mode 100644 app/api/uploads/ActivityPool-1729789161739-111170816.sol delete mode 100644 app/api/uploads/ActivityPool-1729789209485-72963277.sol delete mode 100644 app/api/uploads/ActivityPool-1729789257596-770519629.sol delete mode 100644 app/api/uploads/ActivityPool-1729789540985-915752235.sol delete mode 100644 app/api/uploads/ActivityPool-1729791081574-279065936.sol delete mode 100644 app/api/uploads/ActivityPool-1729807762472-693738646.sol delete mode 100644 app/api/uploads/ActivityPool-1729808024413-309876997.sol delete mode 100644 app/api/uploads/ActivityPool-1729808113420-601666536.sol delete mode 100644 app/api/uploads/ActivityPool-1729808507370-473274218.sol delete mode 100644 app/api/uploads/ActivityPool-1729808603511-614676959.sol delete mode 100644 app/api/uploads/ActivityPool-1729820423782-940160024.sol delete mode 100644 app/api/uploads/ActivityPool-1729820471994-34420655.sol delete mode 100644 app/api/uploads/ActivityPool-1729820576582-824190408.sol delete mode 100644 app/api/uploads/ActivityPool-1729821244300-939222585.sol delete mode 100644 app/api/uploads/ActivityPool-1729821496223-688339861.sol delete mode 100644 app/api/uploads/ActivityPool-1729821817840-171758606.sol delete mode 100644 app/api/uploads/ActivityPool-1729821940759-282179510.sol delete mode 100644 app/api/uploads/ActivityPool-1729821993926-279009626.sol delete mode 100644 app/api/uploads/ActivityPool-1729822490209-444268394.sol delete mode 100644 app/api/uploads/ActivityPool-1729823113167-316818505.sol delete mode 100644 app/api/uploads/ActivityPool-1729823400774-680295923.sol delete mode 100644 app/api/uploads/ActivityPool-1729823724402-583299337.sol delete mode 100644 app/api/uploads/ActivityPool-1729824294573-151604978.sol delete mode 100644 app/api/uploads/ActivityPool-1729824388248-854683049.sol delete mode 100644 app/api/uploads/ActivityPool-1729824663495-208623935.sol delete mode 100644 app/api/uploads/ActivityPool-1729824691606-708783209.sol delete mode 100644 app/api/uploads/ActivityPool-1729824763048-505946666.sol delete mode 100644 app/api/uploads/Test_1-1729808659268-441728940.sol diff --git a/app/api/backend.mjs b/app/api/backend.mjs index 16bd1f2..c5bd1b4 100644 --- a/app/api/backend.mjs +++ b/app/api/backend.mjs @@ -10,7 +10,8 @@ import { dirname } from 'path'; import fs from 'fs/promises'; import { exec } from 'child_process'; import { promisify } from 'util'; -import {Timer} from './timer.mjs' +import { Timer } from './timer.mjs'; + // Initialize environment variables dotenv.config(); @@ -22,243 +23,146 @@ const __filename = fileURLToPath(import.meta.url); const __dirname = dirname(__filename); const UPLOADS_DIR = path.join(__dirname, 'uploads'); -// Create uploads directory if it doesn't exist -try { - await fs.mkdir(UPLOADS_DIR, { recursive: true }); -} catch (error) { - console.error('Error creating uploads directory:', error); +// Ensure uploads directory exists +async function ensureUploadsDirectory() { + try { + await fs.mkdir(UPLOADS_DIR, { recursive: true }); + } catch (error) { + console.error('Error creating uploads directory:', error); + throw error; + } } -// Initialize Express app -const app = express(); - -// Middleware -app.use(express.json()); -app.use(express.urlencoded({ extended: true })); - // Initialize Supabase -const supabaseUrl = process.env.NEXT_PUBLIC_SUPABASE_URL; -const supabaseKey = process.env.NEXT_PUBLIC_SUPABASE_ANON_KEY; +function initializeSupabase() { + const supabaseUrl = process.env.NEXT_PUBLIC_SUPABASE_URL; + const supabaseKey = process.env.NEXT_PUBLIC_SUPABASE_ANON_KEY; + + if (!supabaseUrl || !supabaseKey) { + throw new Error('Missing Supabase credentials'); + } -if (!supabaseUrl || !supabaseKey) { - console.error('Missing Supabase credentials'); - process.exit(1); + return createClient(supabaseUrl, supabaseKey); } -//connect to supabase -const supabase = createClient(supabaseUrl, supabaseKey); - -// CORS configuration -const corsOptions = { - origin: ['http://localhost:3000', 'http://localhost:3001', 'https://blockscan-swin.vercel.app'], - methods: ['GET', 'POST', 'PUT', 'DELETE', 'OPTIONS'], - allowedHeaders: ['Content-Type', 'Authorization'], - credentials: true -}; -app.use(cors(corsOptions)); +// Initialize Express and middleware +function initializeExpress() { + const app = express(); + app.use(express.json()); + app.use(express.urlencoded({ extended: true })); + + // CORS configuration + const corsOptions = { + origin: ['http://localhost:3000', 'http://localhost:3001', 'https://blockscan-swin.vercel.app'], + methods: ['GET', 'POST', 'PUT', 'DELETE', 'OPTIONS'], + allowedHeaders: ['Content-Type', 'Authorization'], + credentials: true + }; + app.use(cors(corsOptions)); + + return { app, corsOptions }; +} // Multer configuration const storage = multer.diskStorage({ - destination: (_req, _file, cb) => { - cb(null, UPLOADS_DIR); - }, - filename: (_req, file, cb) => { - const uniqueSuffix = `${Date.now()}-${Math.round(Math.random() * 1E9)}`; - cb(null, `${path.parse(file.originalname).name}-${uniqueSuffix}.sol`); - } + destination: (_req, _file, cb) => { + cb(null, UPLOADS_DIR); + }, + filename: (_req, file, cb) => { + const uniqueSuffix = `${Date.now()}-${Math.round(Math.random() * 1E9)}`; + cb(null, `${path.parse(file.originalname).name}-${uniqueSuffix}.sol`); + } }); const upload = multer({ - storage, - fileFilter: (_req, file, cb) => { - if (!file.originalname.toLowerCase().endsWith('.sol')) { - return cb(new Error('Only .sol files are allowed')); + storage, + fileFilter: (_req, file, cb) => { + if (!file.originalname.toLowerCase().endsWith('.sol')) { + return cb(new Error('Only .sol files are allowed')); + } + cb(null, true); + }, + limits: { + fileSize: 10 * 1024 * 1024 // 10MB limit } - cb(null, true); - }, - limits: { - fileSize: 10 * 1024 * 1024 // 10MB limit - } -}); - - -// Health check -app.get('/health', (_req, res) => { - res.json({ status: 'ok', message: 'Server is running' }); }); - -// File upload endpoint -app.post('/contract-upload', upload.single('contractFile'), async (req, res) => { +// Slither analysis functions +async function executeSlitherAnalysis(filePath) { try { - console.log('Received upload request'); - if (!req.file) { - return res.status(400).json({ - status: 'error', - message: 'No file uploaded' - }); - } - - res.status(200).json({ - status: 'success', - message: 'File uploaded successfully', - data: { - filename: req.file.filename + const options = { + maxBuffer: 1024 * 1024 * 50 // 50MB buffer + }; + + // Execute single Slither command for analysis + let slitherOutput = ''; + try { + const { stdout, stderr } = await execAsync(`slither "${filePath}" --print human-summary`, options); + + // Combine stdout and stderr as Slither might output to either + slitherOutput = stdout || ''; + if (stderr) { + console.log('Slither stderr:', stderr); + // Only add stderr if it contains useful information + if (stderr.includes('contracts in source files') || + stderr.includes('Source lines of code') || + stderr.includes('Number of')) { + slitherOutput += '\n' + stderr; + } + } + } catch (execError) { + console.error('Slither execution error:', execError); + // Even if the command fails, we might have useful output + slitherOutput = execError.stdout || ''; + if (execError.stderr) { + console.log('Error stderr:', execError.stderr); + if (execError.stderr.includes('contracts in source files') || + execError.stderr.includes('Source lines of code') || + execError.stderr.includes('Number of')) { + slitherOutput += '\n' + execError.stderr; + } + } } - }); - } catch (error) { - console.error('Upload error:', error); - res.status(500).json({ - status: 'error', - message: error.message || 'File upload failed' - }); - } -}); - -// Replace the contract analysis endpoint with this fixed version -app.post('/contract-analyze', async (req, res) => { - const timer = new Timer(); - timer.start(); - try { - - const { projectName, filename } = req.body; - console.log('Analyzing:', { projectName, filename }); - - if (!projectName || !filename) { - return res.status(400).json({ - status: 'error', - message: 'Project name and filename are required' - }); - } - - const filePath = path.join(UPLOADS_DIR, filename); - - try { - await fs.access(filePath); - } catch { - return res.status(404).json({ - status: 'error', - message: 'Contract file not found' - }); - } - // Execute Slither with better output handling - let slitherOutput = ''; - try { - const { stdout, stderr } = await execAsync(`slither "${filePath}" --print human-summary`); - - // Combine stdout and stderr as Slither might output to either - slitherOutput = stdout || ''; - if (stderr) { - console.log('Slither stderr:', stderr); - // Only add stderr if it contains useful information - if (stderr.includes('contracts in source files') || - stderr.includes('Source lines of code') || - stderr.includes('Number of')) { - slitherOutput += '\n' + stderr; - } - } - } catch (execError) { - console.error('Slither execution error:', execError); - // Even if the command fails, we might have useful output - slitherOutput = execError.stdout || ''; - if (execError.stderr) { - console.log('Error stderr:', execError.stderr); - if (execError.stderr.includes('contracts in source files') || - execError.stderr.includes('Source lines of code') || - execError.stderr.includes('Number of')) { - slitherOutput += '\n' + execError.stderr; - } + if (!slitherOutput.trim()) { + throw new Error('No output received from Slither analysis'); } - } - if (!slitherOutput.trim()) { - throw new Error('No output received from Slither analysis'); - } + // Clean the output + const cleanOutput = slitherOutput + .replace(/\u001b\[\d+m/g, '') // Remove ANSI color codes + .replace(/\r\n/g, '\n') // Normalize line endings + .trim(); + + // For vulnerabilities, run a separate detailed analysis + let vulnsOutput = ''; + try { + const { stdout: vulnsStdout, stderr: vulnsStderr } = await execAsync(`slither "${filePath}"`, options); + vulnsOutput = (vulnsStdout || '') + (vulnsStderr || ''); + } catch (vulnError) { + console.error('Vulnerability analysis error:', vulnError); + vulnsOutput = (vulnError.stdout || '') + (vulnError.stderr || ''); + } + const cleanVulns = vulnsOutput + .replace(/\u001b\[\d+m/g, '') + .replace(/\r\n/g, '\n') + .trim(); - // Clean the output before parsing - const cleanOutput = slitherOutput - .replace(/\u001b\[\d+m/g, '') // Remove ANSI color codes - .replace(/\r\n/g, '\n') // Normalize line endings - .trim(); - - - // Stop timer before database operations - const scanDuration = timer.stop(); - // Parse the cleaned output - const metrics = parseSlitherOutput(cleanOutput, scanDuration); - - // Convert all numeric values explicitly - const metricsData = { - project_name: projectName, - total_contracts: parseInt(metrics.total_contracts) || 0, - source_lines: parseInt(metrics.source_lines) || 0, - assembly_lines: parseInt(metrics.assembly_lines) || 0, - scan_duration: scanDuration, - optimization_issues: parseInt(metrics.optimization_issues) || 0, - informational_issues: parseInt(metrics.informational_issues) || 0, - low_issues: parseInt(metrics.low_issues) || 0, - medium_issues: parseInt(metrics.medium_issues) || 0, - high_issues: parseInt(metrics.high_issues) || 0, - ercs: metrics.ercs || 'None' - }; + return { + overview: cleanOutput, + vulns: cleanVulns + }; + } catch (error) { + console.error('Slither execution error:', error); + throw error; + } +} - // Save to Supabase - const { data, error } = await supabase - .from('slither_metrics') - .insert([metricsData]) - .select(); - if (error) { - console.error('Supabase error:', error); - throw new Error(`Database error: ${error.message}`); - } - // Clean up file - try { - await fs.unlink(filePath); - console.log('Cleaned up file:', filePath); - } catch (cleanupError) { - console.error('Error cleaning up file:', cleanupError); - } - timer.stop(); - res.status(200).json({ - status: 'success', - message: 'Analysis completed successfully', - data: { - projectName, - metrics: { - total_contracts: metrics.total_contracts, - source_lines: metrics.source_lines, - assembly_lines: metrics.assembly_lines, - scan_duration: metrics.scan_duration, - issues: { - optimization: metrics.optimization_issues, - informational: metrics.informational_issues, - low: metrics.low_issues, - medium: metrics.medium_issues, - high: metrics.high_issues, - }, - ercs: metrics.ercs - }, - timestamp: new Date().toISOString(), - id: data?.[0]?.id - } - }); - } catch (error) { - timer.stop(); - console.error('Analysis error:', error); - res.status(500).json({ - status: 'error', - message: error.message || 'Analysis failed', - details: error.stack - }); - } -}); - -// And update the parseSlitherOutput function +// Parse Slither output const parseSlitherOutput = (output, scanDuration) => { try { // Initialize metrics with default values @@ -327,38 +231,336 @@ const parseSlitherOutput = (output, scanDuration) => { } }; +// Parse Slither vulnerabilities +function parseSlitherVulns(slitherVulns) { + const vulnsArray = []; + const lines = slitherVulns.split('\n') + .map(line => line.trim()) + .filter(line => line.length > 0); + + const vulnerabilityTypes = { + 'abiencoderv2-array': 'Storage ABIEncoderV2 Array', + 'arbitrary-send-erc20': 'Arbitrary from in transferFrom', + 'array-by-reference': 'Modifying storage array by value', + 'encode-packed-collision': 'ABI encodePacked Collision', + 'incorrect-shift': 'ABI encodePacked Collision', + 'multiple-constructors': 'Multiple constructor schemes', + 'name-reused': 'Name reused', + 'protected-vars': 'Protected Variables', + 'public-mappings-nested': 'Public mappings with nested variables', + 'rtlo': 'Right-to-Left-Override character', + 'shadowing-state': 'State variable shadowing', + 'suicidal': 'Suicidal', + 'uninitialized-state': 'Uninitialized state variables', + 'uninitialized-storage': 'Uninitialized storage variables', + 'unprotected-upgrade': 'Unprotected upgradeable contract', + 'codex': 'Codex', + 'arbitrary-send-erc20-permit': 'Arbitrary from in transferFrom used with permit', + 'arbitrary-send-eth': 'Functions that send Ether to arbitrary destinations', + 'controlled-array-length': 'Array Length Assignment', + 'controlled-delegatecall': 'Controlled Delegatecall', + 'delegatecall-loop': 'Payable functions using delegatecall inside a loop', + 'incorrect-exp': 'Incorrect exponentiation', + 'incorrect-return': 'Incorrect return in assembly', + 'msg-value-loop': 'msg value loop', + 'reentrancy-eth': 'reentrancy eth', + 'return-leave': 'return leave', + 'storage-array': 'storage array', + 'unchecked-transfer': 'unchecked transfer', + 'weak-prng': 'weak prng', + 'domain-separator-collision': 'domain separator collision', + 'enum-conversion': 'enum conversion', + 'erc20-interface': 'erc20 interface', + 'erc721-interface': 'erc721 interface', + 'incorrect-equality': 'incorrect equality', + 'locked-ether': 'locked ether', + 'mapping-deletion': 'mapping deletion', + 'shadowing-abstract': 'shadowing abstract', + 'tautological-compare': 'tautological compare', + 'tautology': 'tautology', + 'write-after-write': 'write after write', + 'boolean-cst': 'boolean cst', + 'constant-function-asm': 'constant function asm', + 'constant-function-state': 'constant function state', + 'divide-before-multiply': 'divide before multiply', + 'out-of-order-retryable': 'out of order retryable', + 'reentrancy-no-eth': 'reentrancy no eth', + 'reused-constructor': 'reused constructor', + 'tx-origin': 'tx origin', + 'unchecked-lowlevel': 'unchecked lowlevel', + 'unchecked-send': 'unchecked send', + 'uninitialized-local': 'uninitialized local', + 'incorrect-modifier': 'incorrect modifier', + 'shadowing-builtin': 'shadowing builtin', + 'shadowing-local': 'shadowing local', + 'uninitialized-fptr-cst': 'uninitialized fptr cst', + 'variable-scope': 'variable scope', + 'void-cst': 'void cst', + 'calls-loop': 'calls loop', + 'events-maths': 'events maths', + 'incorrect-unary': 'incorrect unary', + 'reentrancy-benign': 'reentrancy benign', + 'return-bomb': 'return bomb', + 'assert-state-change': 'assert state change', + 'boolean-equal': 'boolean equal', + 'cyclomatic-complexity': 'cyclomatic complexity', + 'deprecated-standards': 'deprecated standards', + 'erc20-indexed': 'erc20 indexed', + 'function-init-state': 'function init state', + 'incorrect-using-for': 'incorrect using for', + 'low-level-calls': 'Low-level calls', + 'missing-inheritance': 'missing inheritance', + 'conformance-to-solidity-naming-convention': 'Conformance to Solidity naming conventions', + 'pragma': 'pragma', + 'redundant-statements': 'redundant statements', + 'incorrect-version': 'Incorrect versions of Solidity', + 'unimplemented-functions': 'unimplemented functions', + 'unused-import': 'Unused Import', + 'unused-state': 'Unused state variable', + 'costly-loop': 'costly loop', + 'dead-code': 'dead code', + 'reentrancy-vulnerabilities-4': 'Reentrancy vulnerabilities', + 'too-many-digits': 'too many digits', + 'cache-array-length': 'cache array length', + 'constable-states': 'constable states', + 'external-function': 'external function', + 'immutable-states': 'immutable states', + 'var-read-using-this': 'var read using this', + 'unused-return': 'Unused Return Value', + 'missing-events-access-control': 'Missing Events Access Control', + 'missing-zero-address-validation': 'Missing Zero Address Validation', + 'reentrancy-vulnerabilities-3': 'Reentrancy Vulnerabilities', + 'block-timestamp': 'Block timestamp', + 'assembly-usage': 'Assembly usage', + 'dead-code': 'Dead-code', + }; + + lines.forEach(line => { + Object.entries(vulnerabilityTypes).forEach(([key, value]) => { + if (line.includes(key)) { + vulnsArray.push(value); + } + }); + }); + return vulnsArray; +} +// Database operations +async function saveVulnerabilities(supabase, metricsId, vulnsArray) { + try { + const vulnsData = await Promise.all( + vulnsArray + .filter(vuln => vuln) + .map(async (vuln) => { + const { data, error } = await supabase + .from('vulnerabilities') + .insert([{ + metrics_id: metricsId, + vulnerability: vuln + }]) + .select(); + + if (error) throw error; + return data[0]; + }) + ); + + return vulnsData.filter(data => data !== null); + } catch (error) { + console.error('Error saving vulnerabilities:', error); + throw error; + } +} +// Main application setup +async function setupApplication() { + try { + // Initialize everything + await ensureUploadsDirectory(); + const supabase = initializeSupabase(); + const { app, corsOptions } = initializeExpress(); + + // Health check endpoint + app.get('/health', (_req, res) => { + res.json({ status: 'ok', message: 'Server is running' }); + }); + + // File upload endpoint + app.post('/contract-upload', upload.single('contractFile'), async (req, res) => { + try { + if (!req.file) { + return res.status(400).json({ + status: 'error', + message: 'No file uploaded' + }); + } + + res.status(200).json({ + status: 'success', + message: 'File uploaded successfully', + data: { + filename: req.file.filename + } + }); + } catch (error) { + console.error('Upload error:', error); + res.status(500).json({ + status: 'error', + message: error.message || 'File upload failed' + }); + } + }); + + // Contract analysis endpoint + app.post('/contract-analyze', async (req, res) => { + const timer = new Timer(); + timer.start(); + let filePath; + + try { + const { projectName, filename } = req.body; + console.log('Analyzing:', { projectName, filename }); + + if (!projectName || !filename) { + return res.status(400).json({ + status: 'error', + message: 'Project name and filename are required' + }); + } + + filePath = path.join(UPLOADS_DIR, filename); + + try { + await fs.access(filePath); + } catch { + return res.status(404).json({ + status: 'error', + message: 'Contract file not found' + }); + } + + // Execute Slither analysis with new implementation + const analysisResult = await executeSlitherAnalysis(filePath); + + // Parse results + const scanDuration = timer.stop(); + const metrics = parseSlitherOutput(analysisResult.overview, scanDuration); + const vulnerabilities = parseSlitherVulns(analysisResult.vulns); + + // Convert all numeric values explicitly for database + const dbMetrics = { + project_name: projectName, + total_contracts: parseInt(metrics.total_contracts) || 0, + source_lines: parseInt(metrics.source_lines) || 0, + assembly_lines: parseInt(metrics.assembly_lines) || 0, + scan_duration: scanDuration, + optimization_issues: parseInt(metrics.optimization_issues) || 0, + informational_issues: parseInt(metrics.informational_issues) || 0, + low_issues: parseInt(metrics.low_issues) || 0, + medium_issues: parseInt(metrics.medium_issues) || 0, + high_issues: parseInt(metrics.high_issues) || 0, + ercs: metrics.ercs || 'None' + }; + + // Save to database + const { data: metricsData, error: metricsError } = await supabase + .from('slither_metrics') + .insert([dbMetrics]) + .select(); + + if (metricsError) throw metricsError; + + // Save vulnerabilities + if (vulnerabilities.length > 0) { + const vulnRecords = vulnerabilities.map(vuln => ({ + metrics_id: metricsData[0].id, + vulnerability: vuln + })); + + const { error: vulnsError } = await supabase + .from('vulnerabilities') + .insert(vulnRecords); + + if (vulnsError) throw vulnsError; + } + + // Cleanup + try { + await fs.unlink(filePath); + console.log('Cleaned up file:', filePath); + } catch (cleanupError) { + console.error('Error cleaning up file:', cleanupError); + } + + res.status(200).json({ + status: 'success', + message: 'Analysis completed successfully', + data: { + projectName, + metrics: { + total_contracts: metrics.total_contracts, + source_lines: metrics.source_lines, + assembly_lines: metrics.assembly_lines, + scan_duration: metrics.scan_duration, + issues: { + optimization: metrics.optimization_issues, + informational: metrics.informational_issues, + low: metrics.low_issues, + medium: metrics.medium_issues, + high: metrics.high_issues, + }, + }, + vulnerabilities: vulnerabilities, + timestamp: new Date().toISOString(), + id: metricsData[0].id + } + }); + + } catch (error) { + console.error('Analysis error:', error); + if (filePath) { + try { + await fs.unlink(filePath); + } catch (cleanupError) { + console.error('Error cleaning up file:', cleanupError); + } + } + res.status(500).json({ + status: 'error', + message: error.message || 'Analysis failed' + }); + } + }); + // Start server + const PORT = process.env.PORT || 5000; + app.listen(PORT, () => { + console.log(`Server running on port ${PORT}`); + console.log(`Uploads directory: ${UPLOADS_DIR}`); + console.log('CORS enabled for:', corsOptions.origin); + }); + + // Handle shutdown + process.on('SIGTERM', async () => { + console.log('SIGTERM received. Cleaning up...'); + try { + const files = await fs.readdir(UPLOADS_DIR); + await Promise.all(files.map(file => fs.unlink(path.join(UPLOADS_DIR, file)))); + } catch (error) { + console.error('Cleanup error:', error); + } + process.exit(0); + }); + + } catch (error) { + console.error('Application setup failed:', error); + process.exit(1); + } +} - - - - - - - - - -///////////////////////////////////////////////////////////////////////////////////////////////////////////////////// - -// Start server -const PORT = process.env.PORT || 5000; -app.listen(PORT, () => { - console.log(`Server running on port ${PORT}`); - console.log(`Uploads directory: ${UPLOADS_DIR}`); - console.log('CORS enabled for:', corsOptions.origin); -}); - -// Handle shutdown -process.on('SIGTERM', async () => { - console.log('SIGTERM received. Cleaning up...'); - try { - const files = await fs.readdir(UPLOADS_DIR); - await Promise.all(files.map(file => fs.unlink(path.join(UPLOADS_DIR, file)))); - } catch (error) { - console.error('Cleanup error:', error); - } - process.exit(0); +// Start the application +setupApplication().catch(error => { + console.error('Fatal error:', error); + process.exit(1); }); \ No newline at end of file diff --git a/app/api/uploads/ActivityPool-1729788732008-144976194.sol b/app/api/uploads/ActivityPool-1729788732008-144976194.sol deleted file mode 100644 index daf3372..0000000 --- a/app/api/uploads/ActivityPool-1729788732008-144976194.sol +++ /dev/null @@ -1,1648 +0,0 @@ -// SPDX-License-Identifier: MIT -// OpenZeppelin Contracts (last updated v4.7.0) (utils/Address.sol) - -pragma solidity ^0.8.1; - -/** - * @dev Collection of functions related to the address type - */ -library Address { - /** - * @dev Returns true if `account` is a contract. - * - * [IMPORTANT] - * ==== - * It is unsafe to assume that an address for which this function returns - * false is an externally-owned account (EOA) and not a contract. - * - * Among others, `isContract` will return false for the following - * types of addresses: - * - * - an externally-owned account - * - a contract in construction - * - an address where a contract will be created - * - an address where a contract lived, but was destroyed - * ==== - * - * [IMPORTANT] - * ==== - * You shouldn't rely on `isContract` to protect against flash loan attacks! - * - * Preventing calls from contracts is highly discouraged. It breaks composability, breaks support for smart wallets - * like Gnosis Safe, and does not provide security since it can be circumvented by calling from a contract - * constructor. - * ==== - */ - function isContract(address account) internal view returns (bool) { - // This method relies on extcodesize/address.code.length, which returns 0 - // for contracts in construction, since the code is only stored at the end - // of the constructor execution. - - return account.code.length > 0; - } - - /** - * @dev Replacement for Solidity's `transfer`: sends `amount` wei to - * `recipient`, forwarding all available gas and reverting on errors. - * - * https://eips.ethereum.org/EIPS/eip-1884[EIP1884] increases the gas cost - * of certain opcodes, possibly making contracts go over the 2300 gas limit - * imposed by `transfer`, making them unable to receive funds via - * `transfer`. {sendValue} removes this limitation. - * - * https://diligence.consensys.net/posts/2019/09/stop-using-soliditys-transfer-now/[Learn more]. - * - * IMPORTANT: because control is transferred to `recipient`, care must be - * taken to not create reentrancy vulnerabilities. Consider using - * {ReentrancyGuard} or the - * https://solidity.readthedocs.io/en/v0.5.11/security-considerations.html#use-the-checks-effects-interactions-pattern[checks-effects-interactions pattern]. - */ - function sendValue(address payable recipient, uint256 amount) internal { - require(address(this).balance >= amount, "Address: insufficient balance"); - - (bool success, ) = recipient.call{value: amount}(""); - require(success, "Address: unable to send value, recipient may have reverted"); - } - - /** - * @dev Performs a Solidity function call using a low level `call`. A - * plain `call` is an unsafe replacement for a function call: use this - * function instead. - * - * If `target` reverts with a revert reason, it is bubbled up by this - * function (like regular Solidity function calls). - * - * Returns the raw returned data. To convert to the expected return value, - * use https://solidity.readthedocs.io/en/latest/units-and-global-variables.html?highlight=abi.decode#abi-encoding-and-decoding-functions[`abi.decode`]. - * - * Requirements: - * - * - `target` must be a contract. - * - calling `target` with `data` must not revert. - * - * _Available since v3.1._ - */ - function functionCall(address target, bytes memory data) internal returns (bytes memory) { - return functionCallWithValue(target, data, 0, "Address: low-level call failed"); - } - - /** - * @dev Same as {xref-Address-functionCall-address-bytes-}[`functionCall`], but with - * `errorMessage` as a fallback revert reason when `target` reverts. - * - * _Available since v3.1._ - */ - function functionCall( - address target, - bytes memory data, - string memory errorMessage - ) internal returns (bytes memory) { - return functionCallWithValue(target, data, 0, errorMessage); - } - - /** - * @dev Same as {xref-Address-functionCall-address-bytes-}[`functionCall`], - * but also transferring `value` wei to `target`. - * - * Requirements: - * - * - the calling contract must have an ETH balance of at least `value`. - * - the called Solidity function must be `payable`. - * - * _Available since v3.1._ - */ - function functionCallWithValue( - address target, - bytes memory data, - uint256 value - ) internal returns (bytes memory) { - return functionCallWithValue(target, data, value, "Address: low-level call with value failed"); - } - - /** - * @dev Same as {xref-Address-functionCallWithValue-address-bytes-uint256-}[`functionCallWithValue`], but - * with `errorMessage` as a fallback revert reason when `target` reverts. - * - * _Available since v3.1._ - */ - function functionCallWithValue( - address target, - bytes memory data, - uint256 value, - string memory errorMessage - ) internal returns (bytes memory) { - require(address(this).balance >= value, "Address: insufficient balance for call"); - (bool success, bytes memory returndata) = target.call{value: value}(data); - return verifyCallResultFromTarget(target, success, returndata, errorMessage); - } - - /** - * @dev Same as {xref-Address-functionCall-address-bytes-}[`functionCall`], - * but performing a static call. - * - * _Available since v3.3._ - */ - function functionStaticCall(address target, bytes memory data) internal view returns (bytes memory) { - return functionStaticCall(target, data, "Address: low-level static call failed"); - } - - /** - * @dev Same as {xref-Address-functionCall-address-bytes-string-}[`functionCall`], - * but performing a static call. - * - * _Available since v3.3._ - */ - function functionStaticCall( - address target, - bytes memory data, - string memory errorMessage - ) internal view returns (bytes memory) { - (bool success, bytes memory returndata) = target.staticcall(data); - return verifyCallResultFromTarget(target, success, returndata, errorMessage); - } - - /** - * @dev Same as {xref-Address-functionCall-address-bytes-}[`functionCall`], - * but performing a delegate call. - * - * _Available since v3.4._ - */ - function functionDelegateCall(address target, bytes memory data) internal returns (bytes memory) { - return functionDelegateCall(target, data, "Address: low-level delegate call failed"); - } - - /** - * @dev Same as {xref-Address-functionCall-address-bytes-string-}[`functionCall`], - * but performing a delegate call. - * - * _Available since v3.4._ - */ - function functionDelegateCall( - address target, - bytes memory data, - string memory errorMessage - ) internal returns (bytes memory) { - (bool success, bytes memory returndata) = target.delegatecall(data); - return verifyCallResultFromTarget(target, success, returndata, errorMessage); - } - - /** - * @dev Tool to verify that a low level call to smart-contract was successful, and revert (either by bubbling - * the revert reason or using the provided one) in case of unsuccessful call or if target was not a contract. - * - * _Available since v4.8._ - */ - function verifyCallResultFromTarget( - address target, - bool success, - bytes memory returndata, - string memory errorMessage - ) internal view returns (bytes memory) { - if (success) { - if (returndata.length == 0) { - // only check isContract if the call was successful and the return data is empty - // otherwise we already know that it was a contract - require(isContract(target), "Address: call to non-contract"); - } - return returndata; - } else { - _revert(returndata, errorMessage); - } - } - - /** - * @dev Tool to verify that a low level call was successful, and revert if it wasn't, either by bubbling the - * revert reason or using the provided one. - * - * _Available since v4.3._ - */ - function verifyCallResult( - bool success, - bytes memory returndata, - string memory errorMessage - ) internal pure returns (bytes memory) { - if (success) { - return returndata; - } else { - _revert(returndata, errorMessage); - } - } - - function _revert(bytes memory returndata, string memory errorMessage) private pure { - // Look for revert reason and bubble it up if present - if (returndata.length > 0) { - // The easiest way to bubble the revert reason is using memory via assembly - /// @solidity memory-safe-assembly - assembly { - let returndata_size := mload(returndata) - revert(add(32, returndata), returndata_size) - } - } else { - revert(errorMessage); - } - } -} - -// OpenZeppelin Contracts (last updated v4.6.0) (token/ERC20/IERC20.sol) - - - -/** - * @dev Interface of the ERC20 standard as defined in the EIP. - */ -interface IERC20 { - /** - * @dev Emitted when `value` tokens are moved from one account (`from`) to - * another (`to`). - * - * Note that `value` may be zero. - */ - event Transfer(address indexed from, address indexed to, uint256 value); - - /** - * @dev Emitted when the allowance of a `spender` for an `owner` is set by - * a call to {approve}. `value` is the new allowance. - */ - event Approval(address indexed owner, address indexed spender, uint256 value); - - /** - * @dev Returns the amount of tokens in existence. - */ - function totalSupply() external view returns (uint256); - - /** - * @dev Returns the amount of tokens owned by `account`. - */ - function balanceOf(address account) external view returns (uint256); - - /** - * @dev Moves `amount` tokens from the caller's account to `to`. - * - * Returns a boolean value indicating whether the operation succeeded. - * - * Emits a {Transfer} event. - */ - function transfer(address to, uint256 amount) external returns (bool); - - /** - * @dev Returns the remaining number of tokens that `spender` will be - * allowed to spend on behalf of `owner` through {transferFrom}. This is - * zero by default. - * - * This value changes when {approve} or {transferFrom} are called. - */ - function allowance(address owner, address spender) external view returns (uint256); - - /** - * @dev Sets `amount` as the allowance of `spender` over the caller's tokens. - * - * Returns a boolean value indicating whether the operation succeeded. - * - * IMPORTANT: Beware that changing an allowance with this method brings the risk - * that someone may use both the old and the new allowance by unfortunate - * transaction ordering. One possible solution to mitigate this race - * condition is to first reduce the spender's allowance to 0 and set the - * desired value afterwards: - * https://github.com/ethereum/EIPs/issues/20#issuecomment-263524729 - * - * Emits an {Approval} event. - */ - function approve(address spender, uint256 amount) external returns (bool); - - /** - * @dev Moves `amount` tokens from `from` to `to` using the - * allowance mechanism. `amount` is then deducted from the caller's - * allowance. - * - * Returns a boolean value indicating whether the operation succeeded. - * - * Emits a {Transfer} event. - */ - function transferFrom( - address from, - address to, - uint256 amount - ) external returns (bool); - - - function mint(address account_, uint256 amount_) external; - - function burn(uint256 amount) external; - -} - - - - - - - - - - - -/** - * @dev Wrappers over Solidity's arithmetic operations with added overflow - * checks. - * - * Arithmetic operations in Solidity wrap on overflow. This can easily result - * in bugs, because programmers usually assume that an overflow raises an - * error, which is the standard behavior in high level programming languages. - * `SafeMath` restores this intuition by reverting the transaction when an - * operation overflows. - * - * Using this library instead of the unchecked operations eliminates an entire - * class of bugs, so it's recommended to use it always. - */ -library SafeMath { - /** - * @dev Returns the addition of two unsigned integers, reverting on - * overflow. - * - * Counterpart to Solidity's `+` operator. - * - * Requirements: - * - * - Addition cannot overflow. - */ - function add(uint256 a, uint256 b) internal pure returns (uint256) { - uint256 c = a + b; - require(c >= a, "SafeMath: addition overflow"); - - return c; - } - - /** - * @dev Returns the subtraction of two unsigned integers, reverting on - * overflow (when the result is negative). - * - * Counterpart to Solidity's `-` operator. - * - * Requirements: - * - * - Subtraction cannot overflow. - */ - function sub(uint256 a, uint256 b) internal pure returns (uint256) { - return sub(a, b, "SafeMath: subtraction overflow"); - } - - /** - * @dev Returns the subtraction of two unsigned integers, reverting with custom message on - * overflow (when the result is negative). - * - * Counterpart to Solidity's `-` operator. - * - * Requirements: - * - * - Subtraction cannot overflow. - */ - function sub( - uint256 a, - uint256 b, - string memory errorMessage - ) internal pure returns (uint256) { - require(b <= a, errorMessage); - uint256 c = a - b; - - return c; - } - - /** - * @dev Returns the multiplication of two unsigned integers, reverting on - * overflow. - * - * Counterpart to Solidity's `*` operator. - * - * Requirements: - * - * - Multiplication cannot overflow. - */ - function mul(uint256 a, uint256 b) internal pure returns (uint256) { - // Gas optimization: this is cheaper than requiring 'a' not being zero, but the - // benefit is lost if 'b' is also tested. - // See: https://github.com/OpenZeppelin/openzeppelin-contracts/pull/522 - if (a == 0) { - return 0; - } - - uint256 c = a * b; - require(c / a == b, "SafeMath: multiplication overflow"); - - return c; - } - - /** - * @dev Returns the integer division of two unsigned integers. Reverts on - * division by zero. The result is rounded towards zero. - * - * Counterpart to Solidity's `/` operator. Note: this function uses a - * `revert` opcode (which leaves remaining gas untouched) while Solidity - * uses an invalid opcode to revert (consuming all remaining gas). - * - * Requirements: - * - * - The divisor cannot be zero. - */ - function div(uint256 a, uint256 b) internal pure returns (uint256) { - return div(a, b, "SafeMath: division by zero"); - } - - /** - * @dev Returns the integer division of two unsigned integers. Reverts with custom message on - * division by zero. The result is rounded towards zero. - * - * Counterpart to Solidity's `/` operator. Note: this function uses a - * `revert` opcode (which leaves remaining gas untouched) while Solidity - * uses an invalid opcode to revert (consuming all remaining gas). - * - * Requirements: - * - * - The divisor cannot be zero. - */ - function div( - uint256 a, - uint256 b, - string memory errorMessage - ) internal pure returns (uint256) { - require(b > 0, errorMessage); - uint256 c = a / b; - // assert(a == b * c + a % b); // There is no case in which this doesn't hold - - return c; - } - - /** - * @dev Returns the remainder of dividing two unsigned integers. (unsigned integer modulo), - * Reverts when dividing by zero. - * - * Counterpart to Solidity's `%` operator. This function uses a `revert` - * opcode (which leaves remaining gas untouched) while Solidity uses an - * invalid opcode to revert (consuming all remaining gas). - * - * Requirements: - * - * - The divisor cannot be zero. - */ - function mod(uint256 a, uint256 b) internal pure returns (uint256) { - return mod(a, b, "SafeMath: modulo by zero"); - } - - /** - * @dev Returns the remainder of dividing two unsigned integers. (unsigned integer modulo), - * Reverts with custom message when dividing by zero. - * - * Counterpart to Solidity's `%` operator. This function uses a `revert` - * opcode (which leaves remaining gas untouched) while Solidity uses an - * invalid opcode to revert (consuming all remaining gas). - * - * Requirements: - * - * - The divisor cannot be zero. - */ - function mod( - uint256 a, - uint256 b, - string memory errorMessage - ) internal pure returns (uint256) { - require(b != 0, errorMessage); - return a % b; - } - - // babylonian method (https://en.wikipedia.org/wiki/Methods_of_computing_square_roots#Babylonian_method) - function sqrrt(uint256 a) internal pure returns (uint256 c) { - if (a > 3) { - c = a; - uint256 b = add(div(a, 2), 1); - while (b < c) { - c = b; - b = div(add(div(a, b), b), 2); - } - } else if (a != 0) { - c = 1; - } - } - - /* - * Expects percentage to be trailed by 00, - */ - function percentageAmount(uint256 total_, uint8 percentage_) internal pure returns (uint256 percentAmount_) { - return div(mul(total_, percentage_), 1000); - } - - /* - * Expects percentage to be trailed by 00, - */ - function substractPercentage(uint256 total_, uint8 percentageToSub_) internal pure returns (uint256 result_) { - return sub(total_, div(mul(total_, percentageToSub_), 1000)); - } - - function percentageOfTotal(uint256 part_, uint256 total_) internal pure returns (uint256 percent_) { - return div(mul(part_, 100), total_); - } - - /** - * Taken from Hypersonic https://github.com/M2629/HyperSonic/blob/main/Math.sol - * @dev Returns the average of two numbers. The result is rounded towards - * zero. - */ - function average(uint256 a, uint256 b) internal pure returns (uint256) { - // (a + b) / 2 can overflow, so we distribute - return (a / 2) + (b / 2) + (((a % 2) + (b % 2)) / 2); - } - - function quadraticPricing(uint256 payment_, uint256 multiplier_) internal pure returns (uint256) { - return sqrrt(mul(multiplier_, payment_)); - } - - function bondingCurve(uint256 supply_, uint256 multiplier_) internal pure returns (uint256) { - return mul(multiplier_, supply_); - } -} - -// OpenZeppelin Contracts (last updated v4.7.0) (token/ERC20/utils/SafeERC20.sol) - - - - - -// OpenZeppelin Contracts v4.4.1 (token/ERC20/extensions/draft-IERC20Permit.sol) - - - -/** - * @dev Interface of the ERC20 Permit extension allowing approvals to be made via signatures, as defined in - * https://eips.ethereum.org/EIPS/eip-2612[EIP-2612]. - * - * Adds the {permit} method, which can be used to change an account's ERC20 allowance (see {IERC20-allowance}) by - * presenting a message signed by the account. By not relying on {IERC20-approve}, the token holder account doesn't - * need to send a transaction, and thus is not required to hold Ether at all. - */ -interface IERC20Permit { - /** - * @dev Sets `value` as the allowance of `spender` over ``owner``'s tokens, - * given ``owner``'s signed approval. - * - * IMPORTANT: The same issues {IERC20-approve} has related to transaction - * ordering also apply here. - * - * Emits an {Approval} event. - * - * Requirements: - * - * - `spender` cannot be the zero address. - * - `deadline` must be a timestamp in the future. - * - `v`, `r` and `s` must be a valid `secp256k1` signature from `owner` - * over the EIP712-formatted function arguments. - * - the signature must use ``owner``'s current nonce (see {nonces}). - * - * For more information on the signature format, see the - * https://eips.ethereum.org/EIPS/eip-2612#specification[relevant EIP - * section]. - */ - function permit( - address owner, - address spender, - uint256 value, - uint256 deadline, - uint8 v, - bytes32 r, - bytes32 s - ) external; - - /** - * @dev Returns the current nonce for `owner`. This value must be - * included whenever a signature is generated for {permit}. - * - * Every successful call to {permit} increases ``owner``'s nonce by one. This - * prevents a signature from being used multiple times. - */ - function nonces(address owner) external view returns (uint256); - - /** - * @dev Returns the domain separator used in the encoding of the signature for {permit}, as defined by {EIP712}. - */ - // solhint-disable-next-line func-name-mixedcase - function DOMAIN_SEPARATOR() external view returns (bytes32); -} - - - -/** - * @title SafeERC20 - * @dev Wrappers around ERC20 operations that throw on failure (when the token - * contract returns false). Tokens that return no value (and instead revert or - * throw on failure) are also supported, non-reverting calls are assumed to be - * successful. - * To use this library you can add a `using SafeERC20 for IERC20;` statement to your contract, - * which allows you to call the safe operations as `token.safeTransfer(...)`, etc. - */ -library SafeERC20 { - using Address for address; - - function safeTransfer( - IERC20 token, - address to, - uint256 value - ) internal { - _callOptionalReturn(token, abi.encodeWithSelector(token.transfer.selector, to, value)); - } - - function safeTransferFrom( - IERC20 token, - address from, - address to, - uint256 value - ) internal { - _callOptionalReturn(token, abi.encodeWithSelector(token.transferFrom.selector, from, to, value)); - } - - /** - * @dev Deprecated. This function has issues similar to the ones found in - * {IERC20-approve}, and its usage is discouraged. - * - * Whenever possible, use {safeIncreaseAllowance} and - * {safeDecreaseAllowance} instead. - */ - function safeApprove( - IERC20 token, - address spender, - uint256 value - ) internal { - // safeApprove should only be called when setting an initial allowance, - // or when resetting it to zero. To increase and decrease it, use - // 'safeIncreaseAllowance' and 'safeDecreaseAllowance' - require( - (value == 0) || (token.allowance(address(this), spender) == 0), - "SafeERC20: approve from non-zero to non-zero allowance" - ); - _callOptionalReturn(token, abi.encodeWithSelector(token.approve.selector, spender, value)); - } - - function safeIncreaseAllowance( - IERC20 token, - address spender, - uint256 value - ) internal { - uint256 newAllowance = token.allowance(address(this), spender) + value; - _callOptionalReturn(token, abi.encodeWithSelector(token.approve.selector, spender, newAllowance)); - } - - function safeDecreaseAllowance( - IERC20 token, - address spender, - uint256 value - ) internal { - unchecked { - uint256 oldAllowance = token.allowance(address(this), spender); - require(oldAllowance >= value, "SafeERC20: decreased allowance below zero"); - uint256 newAllowance = oldAllowance - value; - _callOptionalReturn(token, abi.encodeWithSelector(token.approve.selector, spender, newAllowance)); - } - } - - function safePermit( - IERC20Permit token, - address owner, - address spender, - uint256 value, - uint256 deadline, - uint8 v, - bytes32 r, - bytes32 s - ) internal { - uint256 nonceBefore = token.nonces(owner); - token.permit(owner, spender, value, deadline, v, r, s); - uint256 nonceAfter = token.nonces(owner); - require(nonceAfter == nonceBefore + 1, "SafeERC20: permit did not succeed"); - } - - /** - * @dev Imitates a Solidity high-level call (i.e. a regular function call to a contract), relaxing the requirement - * on the return value: the return value is optional (but if data is returned, it must not be false). - * @param token The token targeted by the call. - * @param data The call data (encoded using abi.encode or one of its variants). - */ - function _callOptionalReturn(IERC20 token, bytes memory data) private { - // We need to perform a low level call here, to bypass Solidity's return data size checking mechanism, since - // we're implementing it ourselves. We use {Address.functionCall} to perform this call, which verifies that - // the target address contains contract code and also asserts for success in the low-level call. - - bytes memory returndata = address(token).functionCall(data, "SafeERC20: low-level call failed"); - if (returndata.length > 0) { - // Return data is optional - require(abi.decode(returndata, (bool)), "SafeERC20: ERC20 operation did not succeed"); - } - } -} - - - - - - - - - - - - - - -/** - * @dev Provides information about the current execution context, including the - * sender of the transaction and its data. While these are generally available - * via msg.sender and msg.data, they should not be accessed in such a direct - * manner, since when dealing with meta-transactions the account sending and - * paying for execution may not be the actual sender (as far as an application - * is concerned). - * - * This contract is only required for intermediate, library-like contracts. - */ -abstract contract Context { - function _msgSender() internal view virtual returns (address) { - return msg.sender; - } - - function _msgData() internal view virtual returns (bytes calldata) { - return msg.data; - } -} - - -/** - * @dev Contract module which provides a basic access control mechanism, where - * there is an account (an owner) that can be granted exclusive access to - * specific functions. - * - * By default, the owner account will be the one that deploys the contract. This - * can later be changed with {transferOwnership}. - * - * This module is used through inheritance. It will make available the modifier - * `onlyOwner`, which can be applied to your functions to restrict their use to - * the owner. - */ -abstract contract Ownable is Context { - address private _owner; - - event OwnershipTransferred(address indexed previousOwner, address indexed newOwner); - - /** - * @dev Initializes the contract setting the deployer as the initial owner. - */ - constructor() { - _transferOwnership(_msgSender()); - } - - /** - * @dev Throws if called by any account other than the owner. - */ - modifier onlyOwner() { - _checkOwner(); - _; - } - - /** - * @dev Returns the address of the current owner. - */ - function owner() public view virtual returns (address) { - return _owner; - } - - /** - * @dev Throws if the sender is not the owner. - */ - function _checkOwner() internal view virtual { - require(owner() == _msgSender(), "Ownable: caller is not the owner"); - } - - /** - * @dev Leaves the contract without owner. It will not be possible to call - * `onlyOwner` functions anymore. Can only be called by the current owner. - * - * NOTE: Renouncing ownership will leave the contract without an owner, - * thereby removing any functionality that is only available to the owner. - */ - function renounceOwnership() public virtual onlyOwner { - _transferOwnership(address(0)); - } - - /** - * @dev Transfers ownership of the contract to a new account (`newOwner`). - * Can only be called by the current owner. - */ - function transferOwnership(address newOwner) public virtual onlyOwner { - require(newOwner != address(0), "Ownable: new owner is the zero address"); - _transferOwnership(newOwner); - } - - /** - * @dev Transfers ownership of the contract to a new account (`newOwner`). - * Internal function without access restriction. - */ - function _transferOwnership(address newOwner) internal virtual { - address oldOwner = _owner; - _owner = newOwner; - emit OwnershipTransferred(oldOwner, newOwner); - } -} - - -contract Operator is Ownable { - address public operator; - uint256 constant baseRate = 10000; - - modifier onlyOperator { - require(msg.sender == owner() || msg.sender == operator, "no permission"); - _; - } - - function setOperator(address operator_) external onlyOwner { - operator = operator_; - } - - - function getCurrTime() external view returns(uint256) { - return block.timestamp; - } - - function getBlockNum() external view returns(uint256) { - return block.number; - } - -} - - - - - -/** - * @dev Library for managing - * https://en.wikipedia.org/wiki/Set_(abstract_data_type)[sets] of primitive - * types. - * - * Sets have the following properties: - * - * - Elements are added, removed, and checked for existence in constant time - * (O(1)). - * - Elements are enumerated in O(n). No guarantees are made on the ordering. - * - * ``` - * contract Example { - * // Add the library methods - * using EnumerableSet for EnumerableSet.AddressSet; - * - * // Declare a set state variable - * EnumerableSet.AddressSet private mySet; - * } - * ``` - * - * As of v3.3.0, sets of type `bytes32` (`Bytes32Set`), `address` (`AddressSet`) - * and `uint256` (`UintSet`) are supported. - * - * [WARNING] - * ==== - * Trying to delete such a structure from storage will likely result in data corruption, rendering the structure unusable. - * See https://github.com/ethereum/solidity/pull/11843[ethereum/solidity#11843] for more info. - * - * In order to clean an EnumerableSet, you can either remove all elements one by one or create a fresh instance using an array of EnumerableSet. - * ==== - */ - -library EnumerableSet { - // To implement this library for multiple types with as little code - // repetition as possible, we write it in terms of a generic Set type with - // bytes32 values. - // The Set implementation uses private functions, and user-facing - // implementations (such as AddressSet) are just wrappers around the - // underlying Set. - // This means that we can only create new EnumerableSets for types that fit - // in bytes32. - - struct Set { - // Storage of set values - bytes32[] _values; - // Position of the value in the `values` array, plus 1 because index 0 - // means a value is not in the set. - mapping(bytes32 => uint256) _indexes; - } - - /** - * @dev Add a value to a set. O(1). - * - * Returns true if the value was added to the set, that is if it was not - * already present. - */ - function _add(Set storage set, bytes32 value) private returns (bool) { - if (!_contains(set, value)) { - set._values.push(value); - // The value is stored at length-1, but we add 1 to all indexes - // and use 0 as a sentinel value - set._indexes[value] = set._values.length; - return true; - } else { - return false; - } - } - - /** - * @dev Removes a value from a set. O(1). - * - * Returns true if the value was removed from the set, that is if it was - * present. - */ - function _remove(Set storage set, bytes32 value) private returns (bool) { - // We read and store the value's index to prevent multiple reads from the same storage slot - uint256 valueIndex = set._indexes[value]; - - if (valueIndex != 0) { - // Equivalent to contains(set, value) - // To delete an element from the _values array in O(1), we swap the element to delete with the last one in - // the array, and then remove the last element (sometimes called as 'swap and pop'). - // This modifies the order of the array, as noted in {at}. - - uint256 toDeleteIndex = valueIndex - 1; - uint256 lastIndex = set._values.length - 1; - - if (lastIndex != toDeleteIndex) { - bytes32 lastValue = set._values[lastIndex]; - - // Move the last value to the index where the value to delete is - set._values[toDeleteIndex] = lastValue; - // Update the index for the moved value - set._indexes[lastValue] = valueIndex; // Replace lastValue's index to valueIndex - } - - // Delete the slot where the moved value was stored - set._values.pop(); - - // Delete the index for the deleted slot - delete set._indexes[value]; - - return true; - } else { - return false; - } - } - - /** - * @dev Returns true if the value is in the set. O(1). - */ - function _contains(Set storage set, bytes32 value) private view returns (bool) { - return set._indexes[value] != 0; - } - - /** - * @dev Returns the number of values on the set. O(1). - */ - function _length(Set storage set) private view returns (uint256) { - return set._values.length; - } - - /** - * @dev Returns the value stored at position `index` in the set. O(1). - * - * Note that there are no guarantees on the ordering of values inside the - * array, and it may change when more values are added or removed. - * - * Requirements: - * - * - `index` must be strictly less than {length}. - */ - function _at(Set storage set, uint256 index) private view returns (bytes32) { - return set._values[index]; - } - - /** - * @dev Return the entire set in an array - * - * WARNING: This operation will copy the entire storage to memory, which can be quite expensive. This is designed - * to mostly be used by view accessors that are queried without any gas fees. Developers should keep in mind that - * this function has an unbounded cost, and using it as part of a state-changing function may render the function - * uncallable if the set grows to a point where copying to memory consumes too much gas to fit in a block. - */ - function _values(Set storage set) private view returns (bytes32[] memory) { - return set._values; - } - - // Bytes32Set - - struct Bytes32Set { - Set _inner; - } - - /** - * @dev Add a value to a set. O(1). - * - * Returns true if the value was added to the set, that is if it was not - * already present. - */ - function add(Bytes32Set storage set, bytes32 value) internal returns (bool) { - return _add(set._inner, value); - } - - /** - * @dev Removes a value from a set. O(1). - * - * Returns true if the value was removed from the set, that is if it was - * present. - */ - function remove(Bytes32Set storage set, bytes32 value) internal returns (bool) { - return _remove(set._inner, value); - } - - /** - * @dev Returns true if the value is in the set. O(1). - */ - function contains(Bytes32Set storage set, bytes32 value) internal view returns (bool) { - return _contains(set._inner, value); - } - - /** - * @dev Returns the number of values in the set. O(1). - */ - function length(Bytes32Set storage set) internal view returns (uint256) { - return _length(set._inner); - } - - /** - * @dev Returns the value stored at position `index` in the set. O(1). - * - * Note that there are no guarantees on the ordering of values inside the - * array, and it may change when more values are added or removed. - * - * Requirements: - * - * - `index` must be strictly less than {length}. - */ - function at(Bytes32Set storage set, uint256 index) internal view returns (bytes32) { - return _at(set._inner, index); - } - - /** - * @dev Return the entire set in an array - * - * WARNING: This operation will copy the entire storage to memory, which can be quite expensive. This is designed - * to mostly be used by view accessors that are queried without any gas fees. Developers should keep in mind that - * this function has an unbounded cost, and using it as part of a state-changing function may render the function - * uncallable if the set grows to a point where copying to memory consumes too much gas to fit in a block. - */ - function values(Bytes32Set storage set) internal view returns (bytes32[] memory) { - return _values(set._inner); - } - - // AddressSet - - struct AddressSet { - Set _inner; - } - - /** - * @dev Add a value to a set. O(1). - * - * Returns true if the value was added to the set, that is if it was not - * already present. - */ - function add(AddressSet storage set, address value) internal returns (bool) { - return _add(set._inner, bytes32(uint256(uint160(value)))); - } - - /** - * @dev Removes a value from a set. O(1). - * - * Returns true if the value was removed from the set, that is if it was - * present. - */ - function remove(AddressSet storage set, address value) internal returns (bool) { - return _remove(set._inner, bytes32(uint256(uint160(value)))); - } - - /** - * @dev Returns true if the value is in the set. O(1). - */ - function contains(AddressSet storage set, address value) internal view returns (bool) { - return _contains(set._inner, bytes32(uint256(uint160(value)))); - } - - /** - * @dev Returns the number of values in the set. O(1). - */ - function length(AddressSet storage set) internal view returns (uint256) { - return _length(set._inner); - } - - /** - * @dev Returns the value stored at position `index` in the set. O(1). - * - * Note that there are no guarantees on the ordering of values inside the - * array, and it may change when more values are added or removed. - * - * Requirements: - * - * - `index` must be strictly less than {length}. - */ - function at(AddressSet storage set, uint256 index) internal view returns (address) { - return address(uint160(uint256(_at(set._inner, index)))); - } - - /** - * @dev Return the entire set in an array - * - * WARNING: This operation will copy the entire storage to memory, which can be quite expensive. This is designed - * to mostly be used by view accessors that are queried without any gas fees. Developers should keep in mind that - * this function has an unbounded cost, and using it as part of a state-changing function may render the function - * uncallable if the set grows to a point where copying to memory consumes too much gas to fit in a block. - */ - function values(AddressSet storage set) internal view returns (address[] memory) { - bytes32[] memory store = _values(set._inner); - address[] memory result; - - /// @solidity memory-safe-assembly - assembly { - result := store - } - - return result; - } - - // UintSet - - struct UintSet { - Set _inner; - } - - /** - * @dev Add a value to a set. O(1). - * - * Returns true if the value was added to the set, that is if it was not - * already present. - */ - function add(UintSet storage set, uint256 value) internal returns (bool) { - return _add(set._inner, bytes32(value)); - } - - /** - * @dev Removes a value from a set. O(1). - * - * Returns true if the value was removed from the set, that is if it was - * present. - */ - function remove(UintSet storage set, uint256 value) internal returns (bool) { - return _remove(set._inner, bytes32(value)); - } - - /** - * @dev Returns true if the value is in the set. O(1). - */ - function contains(UintSet storage set, uint256 value) internal view returns (bool) { - return _contains(set._inner, bytes32(value)); - } - - /** - * @dev Returns the number of values on the set. O(1). - */ - function length(UintSet storage set) internal view returns (uint256) { - return _length(set._inner); - } - - /** - * @dev Returns the value stored at position `index` in the set. O(1). - * - * Note that there are no guarantees on the ordering of values inside the - * array, and it may change when more values are added or removed. - * - * Requirements: - * - * - `index` must be strictly less than {length}. - */ - function at(UintSet storage set, uint256 index) internal view returns (uint256) { - return uint256(_at(set._inner, index)); - } - - /** - * @dev Return the entire set in an array - * - * WARNING: This operation will copy the entire storage to memory, which can be quite expensive. This is designed - * to mostly be used by view accessors that are queried without any gas fees. Developers should keep in mind that - * this function has an unbounded cost, and using it as part of a state-changing function may render the function - * uncallable if the set grows to a point where copying to memory consumes too much gas to fit in a block. - */ - function values(UintSet storage set) internal view returns (uint256[] memory) { - bytes32[] memory store = _values(set._inner); - uint256[] memory result; - - /// @solidity memory-safe-assembly - assembly { - result := store - } - - return result; - } -} - - -contract ActivityPool is Operator { - using SafeMath for uint256; - using SafeERC20 for IERC20; - using EnumerableSet for EnumerableSet.AddressSet; - using EnumerableSet for EnumerableSet.UintSet; - - event AddNewAct(uint256 id); - event Bet(address user, uint256 pID, uint256 bType, uint256 amount, uint256 time); - event SetPrize(uint256 pID, uint256 bType); - event Claim(address user, uint256 pID, uint256 bType, uint256 amount); - event RemovePeriodAct(uint256 pID); - - uint256 public constant muti = 1e18; - uint256 public periodID; - uint256 public betID; - - struct UserInfo { - address user; - uint256 pID; - uint256 amount; - uint256 betTime; - uint256 bType; - uint256 claimAmount; - } - - struct ActInfo { - string name; - string aName; - string bName; - address rewardToken; - uint256 startTime; - uint256 endTime; - uint256 minAmount; - uint256 maxAmount; - uint256 aAmount; - uint256 bAmount; - uint256 winType; - bool isBet; - } - - struct TimeInfo { - uint256 time; - uint256 aAmount; - uint256 bAmount; - } - - struct BestInfo { - address aUser; - address bUser; - uint256 aBet; - uint256 bBet; - } - - mapping(uint256 => BestInfo) bestInfo; - mapping(uint256 => uint256) public timeID; - mapping(uint256 => mapping(uint256 => TimeInfo)) public timeInfo; - mapping(address => mapping(uint256 => uint256)) public userBet; - mapping(uint256 => UserInfo) public betInfo; - mapping(uint256 => uint256) public perAmount; - mapping(uint256 => ActInfo) public actInfo; - mapping(uint256 => mapping(uint256 => string)) public descripName; - - mapping(address => EnumerableSet.UintSet) userPid; - mapping(uint256 => EnumerableSet.AddressSet) aUsers; - mapping(uint256 => EnumerableSet.AddressSet) bUsers; - EnumerableSet.UintSet activePeriod; - EnumerableSet.UintSet removePeriod; - - function addNewAct( - string memory name, - string memory aName, - string memory bName, - address token, - uint256 startTime, - uint256 endTime, - uint256 minAmount, - uint256 maxAmount - ) external onlyOperator { - - checkAdd(msg.sender, startTime, endTime, minAmount, maxAmount); - uint256 id = ++periodID; - actInfo[id].name = name; - actInfo[id].aName = aName; - actInfo[id].bName = bName; - actInfo[id].startTime = startTime; - actInfo[id].endTime = endTime; - actInfo[id].minAmount = minAmount; - actInfo[id].maxAmount = maxAmount; - actInfo[id].rewardToken = token; - descripName[id][1] = aName; - descripName[id][2] = bName; - activePeriod.add(id); - - emit AddNewAct(id); - } - - - function removePeriodAct(uint256 pID) external onlyOperator { - checkRemove(pID); - - activePeriod.remove(pID); - removePeriod.add(pID); - - emit RemovePeriodAct(pID); - } - - - function bet(uint256 pID, uint256 bType, uint256 amount) external payable { - checkBet(msg.sender, pID, bType, amount); - if(actInfo[pID].rewardToken == address(0)) { - require(msg.value == amount, "value err"); - } else { - require(msg.value == 0, "value amount err"); - } - - if(bType == 1) { - if(amount > bestInfo[pID].aBet) { - bestInfo[pID].aUser = msg.sender; - bestInfo[pID].aBet = amount; - } - } else { - if(amount > bestInfo[pID].bBet) { - bestInfo[pID].bUser = msg.sender; - bestInfo[pID].bBet = amount; - } - } - - userPid[msg.sender].add(pID); - uint256 id = ++betID; - userBet[msg.sender][pID] = id; - - if(bType == 1) { - aUsers[pID].add(msg.sender); - actInfo[pID].aAmount = actInfo[pID].aAmount.add(amount); - } else { - bUsers[pID].add(msg.sender); - actInfo[pID].bAmount = actInfo[pID].bAmount.add(amount); - } - - actInfo[pID].isBet = true; - betInfo[id].user = msg.sender; - betInfo[id].pID = pID; - betInfo[id].amount = amount; - betInfo[id].betTime = block.timestamp; - betInfo[id].bType = bType; - - uint256 tID = ++timeID[pID]; - timeInfo[pID][tID].time = block.timestamp; - timeInfo[pID][tID].aAmount = actInfo[pID].aAmount; - timeInfo[pID][tID].bAmount = actInfo[pID].bAmount; - - if(actInfo[pID].rewardToken != address(0)) { - IERC20(actInfo[pID].rewardToken).safeTransferFrom(msg.sender, address(this), amount); - } - emit Bet(msg.sender, pID, bType, amount, betInfo[id].betTime); - } - - function setPrize(uint256 pID, uint256 bType) external onlyOperator { - checkSetPrize(msg.sender, pID, bType); - - if(block.timestamp <= actInfo[pID].startTime) { - actInfo[pID].startTime = block.timestamp; - - } - actInfo[pID].endTime = block.timestamp; - - actInfo[pID].winType = bType; - perAmount[pID] = getPerAmount(pID, bType); - - emit SetPrize(pID, bType); - } - - function recive() public payable {} - - function claim(uint256 pID) external { - uint256 amount = checkClaim(msg.sender, pID); - - uint256 id = userBet[msg.sender][pID]; - betInfo[id].claimAmount = amount; - if(actInfo[pID].rewardToken != address(0)) { - IERC20(actInfo[pID].rewardToken).safeTransfer(msg.sender, amount); - } else { - payable(msg.sender).transfer(amount); - } - - emit Claim(msg.sender, pID, betInfo[id].bType, amount); - } - - function checkClaim(address user, uint256 pID) public view returns(uint256 amount) { - require(userPid[user].contains(pID), "not bet"); - uint256 id = userBet[user][pID]; - require(betInfo[id].user == user, "not user"); - require(actInfo[pID].winType != 0, "not prize"); - require(betInfo[id].claimAmount == 0, "has claim"); - - if(actInfo[pID].winType != 3) { - require(actInfo[pID].winType == betInfo[id].bType, "not right"); - amount = perAmount[pID].mul(betInfo[id].amount).div(muti); - require(amount > 0, "no amount"); - } else { - amount = betInfo[id].amount; - } - - return amount; - } - - function getActualRate( - address user, - uint256 pID, - uint256 bType, - uint256 amount - ) external view returns(uint256, uint256, bool) { - if(bType < 1 || bType > 2 || !activePeriod.contains(pID)) { - return (0, 0, false); - } else if(userBet[user][pID] != 0 || actInfo[pID].winType != 0 || amount == 0) { - (uint256 ra, uint256 rb) = getRate(pID, timeID[pID]); - return (ra, rb, false); - } else { - (uint256 aAmount, uint256 bAmount) = (actInfo[pID].aAmount, actInfo[pID].bAmount); - if(bType == 1) { - aAmount = aAmount.add(amount); - } else { - bAmount = bAmount.add(amount); - } - - uint256 total = aAmount.add(bAmount); - if(bAmount == 0 && aAmount != 0) { - return (muti, 0, true); - } - if(bAmount != 0 && aAmount == 0) { - return (0, muti, true); - } - return (total.mul(muti).div(aAmount), total.mul(muti).div(bAmount), true); - } - } - - function getRate(uint256 pID, uint256 tID) public view returns(uint256, uint256) { - (uint256 aAmount, uint256 bAmount) = (timeInfo[pID][tID].aAmount, timeInfo[pID][tID].bAmount); - uint256 total = aAmount.add(bAmount); - if(total == 0) { - return (0, 0); - } - if(bAmount == 0 && aAmount != 0) { - return (muti, 0); - } - if(bAmount != 0 && aAmount == 0) { - return (0, muti); - } - return (total.mul(muti).div(aAmount), total.mul(muti).div(bAmount)); - } - - function getBestInfo(uint256 pID) - external - view - returns(address aUser, address bUser, uint256 aBet, uint256 bBet, uint256 aReward, uint256 bReward) - { - aUser = bestInfo[pID].aUser; - bUser = bestInfo[pID].bUser; - aBet = bestInfo[pID].aBet; - bBet = bestInfo[pID].bBet; - aReward = getPerAmount(pID, 1).mul(aBet).div(muti); - bReward = getPerAmount(pID, 2).mul(bBet).div(muti); - } - - function getPerAmount(uint256 pID, uint256 bType) public view returns(uint256) { - uint256 total = actInfo[pID].aAmount.add(actInfo[pID].bAmount); - if(total == 0) { - return 0; - } - - if(actInfo[pID].winType == 3) { - return muti; - } - - if(bType == 1) { - if(actInfo[pID].aAmount == 0 || actInfo[pID].winType == 2) { - return 0; - } - return total.mul(muti).div(actInfo[pID].aAmount); - } - - if(bType == 2) { - if(actInfo[pID].bAmount == 0 || actInfo[pID].winType == 1) { - return 0; - } - return total.mul(muti).div(actInfo[pID].bAmount); - } - - return 0; - - } - - function checkSetPrize(address user, uint256 pID, uint256 bType) public view returns(bool) { - require(user == owner() || user == operator, "no permission"); - require(bType > 0 && bType <= 3, "type err"); - require(activePeriod.contains(pID), "not active"); - require(actInfo[pID].winType == 0, "has set"); - - return true; - } - - function checkBet( - address user, - uint256 pID, - uint256 bType, - uint256 amount - ) public view returns(bool) { - require(activePeriod.contains(pID), "not active"); - require(actInfo[pID].startTime <= block.timestamp, "not start"); - require(actInfo[pID].endTime > block.timestamp, "has end"); - require(!userPid[user].contains(pID), "has bet"); - require(bType > 0 && bType < 3, "type err"); - require(amount >= actInfo[pID].minAmount && amount <= actInfo[pID].maxAmount, "amount err"); - if(actInfo[pID].rewardToken != address(0)) { - require(IERC20(actInfo[pID].rewardToken).allowance(user, address(this)) >= amount, "not approve enough"); - require(IERC20(actInfo[pID].rewardToken).balanceOf(user) >= amount, "not enough"); - } else { - require(user.balance >= amount, "main token err"); - } - - return true; - } - - - function checkRemove(uint256 pID) public view returns(bool) { - require(activePeriod.contains(pID), "not in"); - require(!actInfo[pID].isBet, "has bet"); - - return true; - } - - function checkAdd( - address user, - uint256 startTime, - uint256 endTime, - uint256 minAmount, - uint256 maxAmount - ) public view returns(bool) { - require(user == owner() || user == operator, "no permission"); - require(startTime > block.timestamp, "startTime err"); - require(endTime > startTime, "endTime err"); - require(minAmount > 0 && maxAmount > minAmount, "amount err"); - - return true; - } - - function getStatus(uint256 pID) external view returns(uint256) { - if(!removePeriod.contains(pID) && !activePeriod.contains(pID)) { - return 5; - } else if(removePeriod.contains(pID)) { - return 6; - } else if(block.timestamp < actInfo[pID].startTime) { - return 1; - } else if ( - actInfo[pID].startTime <= block.timestamp && - actInfo[pID].endTime > block.timestamp - ) { - return 2; - } else if (actInfo[pID].endTime <= block.timestamp && actInfo[pID].winType == 0){ - return 3; - } else if(actInfo[pID].winType != 0) { - return 4; - } - return 0; - } - - function getUserPidNum(address user) external view returns(uint256) { - return userPid[user].length(); - } - - function getUserPid(address user, uint256 index) external view returns(uint256) { - return userPid[user].at(index); - } - - function getAUsersNum(uint256 pID) external view returns(uint256) { - return aUsers[pID].length(); - } - - function getAUsers(uint256 pID, uint256 index) external view returns(address) { - return aUsers[pID].at(index); - } - - function getBUsersNum(uint256 pID) external view returns(uint256) { - return bUsers[pID].length(); - } - - function getBUsers(uint256 pID, uint256 index) external view returns(address) { - return bUsers[pID].at(index); - } - - function getActivePeriodNum() external view returns(uint256) { - return activePeriod.length(); - } - - function getActivePeriod(uint256 index) external view returns(uint256) { - return activePeriod.at(index); - } - - function getRemovePeriodNum() external view returns(uint256) { - return removePeriod.length(); - } - - function getRemovePeriod(uint256 index) external view returns(uint256) { - return removePeriod.at(index); - } -} \ No newline at end of file diff --git a/app/api/uploads/ActivityPool-1729789040141-363580194.sol b/app/api/uploads/ActivityPool-1729789040141-363580194.sol deleted file mode 100644 index daf3372..0000000 --- a/app/api/uploads/ActivityPool-1729789040141-363580194.sol +++ /dev/null @@ -1,1648 +0,0 @@ -// SPDX-License-Identifier: MIT -// OpenZeppelin Contracts (last updated v4.7.0) (utils/Address.sol) - -pragma solidity ^0.8.1; - -/** - * @dev Collection of functions related to the address type - */ -library Address { - /** - * @dev Returns true if `account` is a contract. - * - * [IMPORTANT] - * ==== - * It is unsafe to assume that an address for which this function returns - * false is an externally-owned account (EOA) and not a contract. - * - * Among others, `isContract` will return false for the following - * types of addresses: - * - * - an externally-owned account - * - a contract in construction - * - an address where a contract will be created - * - an address where a contract lived, but was destroyed - * ==== - * - * [IMPORTANT] - * ==== - * You shouldn't rely on `isContract` to protect against flash loan attacks! - * - * Preventing calls from contracts is highly discouraged. It breaks composability, breaks support for smart wallets - * like Gnosis Safe, and does not provide security since it can be circumvented by calling from a contract - * constructor. - * ==== - */ - function isContract(address account) internal view returns (bool) { - // This method relies on extcodesize/address.code.length, which returns 0 - // for contracts in construction, since the code is only stored at the end - // of the constructor execution. - - return account.code.length > 0; - } - - /** - * @dev Replacement for Solidity's `transfer`: sends `amount` wei to - * `recipient`, forwarding all available gas and reverting on errors. - * - * https://eips.ethereum.org/EIPS/eip-1884[EIP1884] increases the gas cost - * of certain opcodes, possibly making contracts go over the 2300 gas limit - * imposed by `transfer`, making them unable to receive funds via - * `transfer`. {sendValue} removes this limitation. - * - * https://diligence.consensys.net/posts/2019/09/stop-using-soliditys-transfer-now/[Learn more]. - * - * IMPORTANT: because control is transferred to `recipient`, care must be - * taken to not create reentrancy vulnerabilities. Consider using - * {ReentrancyGuard} or the - * https://solidity.readthedocs.io/en/v0.5.11/security-considerations.html#use-the-checks-effects-interactions-pattern[checks-effects-interactions pattern]. - */ - function sendValue(address payable recipient, uint256 amount) internal { - require(address(this).balance >= amount, "Address: insufficient balance"); - - (bool success, ) = recipient.call{value: amount}(""); - require(success, "Address: unable to send value, recipient may have reverted"); - } - - /** - * @dev Performs a Solidity function call using a low level `call`. A - * plain `call` is an unsafe replacement for a function call: use this - * function instead. - * - * If `target` reverts with a revert reason, it is bubbled up by this - * function (like regular Solidity function calls). - * - * Returns the raw returned data. To convert to the expected return value, - * use https://solidity.readthedocs.io/en/latest/units-and-global-variables.html?highlight=abi.decode#abi-encoding-and-decoding-functions[`abi.decode`]. - * - * Requirements: - * - * - `target` must be a contract. - * - calling `target` with `data` must not revert. - * - * _Available since v3.1._ - */ - function functionCall(address target, bytes memory data) internal returns (bytes memory) { - return functionCallWithValue(target, data, 0, "Address: low-level call failed"); - } - - /** - * @dev Same as {xref-Address-functionCall-address-bytes-}[`functionCall`], but with - * `errorMessage` as a fallback revert reason when `target` reverts. - * - * _Available since v3.1._ - */ - function functionCall( - address target, - bytes memory data, - string memory errorMessage - ) internal returns (bytes memory) { - return functionCallWithValue(target, data, 0, errorMessage); - } - - /** - * @dev Same as {xref-Address-functionCall-address-bytes-}[`functionCall`], - * but also transferring `value` wei to `target`. - * - * Requirements: - * - * - the calling contract must have an ETH balance of at least `value`. - * - the called Solidity function must be `payable`. - * - * _Available since v3.1._ - */ - function functionCallWithValue( - address target, - bytes memory data, - uint256 value - ) internal returns (bytes memory) { - return functionCallWithValue(target, data, value, "Address: low-level call with value failed"); - } - - /** - * @dev Same as {xref-Address-functionCallWithValue-address-bytes-uint256-}[`functionCallWithValue`], but - * with `errorMessage` as a fallback revert reason when `target` reverts. - * - * _Available since v3.1._ - */ - function functionCallWithValue( - address target, - bytes memory data, - uint256 value, - string memory errorMessage - ) internal returns (bytes memory) { - require(address(this).balance >= value, "Address: insufficient balance for call"); - (bool success, bytes memory returndata) = target.call{value: value}(data); - return verifyCallResultFromTarget(target, success, returndata, errorMessage); - } - - /** - * @dev Same as {xref-Address-functionCall-address-bytes-}[`functionCall`], - * but performing a static call. - * - * _Available since v3.3._ - */ - function functionStaticCall(address target, bytes memory data) internal view returns (bytes memory) { - return functionStaticCall(target, data, "Address: low-level static call failed"); - } - - /** - * @dev Same as {xref-Address-functionCall-address-bytes-string-}[`functionCall`], - * but performing a static call. - * - * _Available since v3.3._ - */ - function functionStaticCall( - address target, - bytes memory data, - string memory errorMessage - ) internal view returns (bytes memory) { - (bool success, bytes memory returndata) = target.staticcall(data); - return verifyCallResultFromTarget(target, success, returndata, errorMessage); - } - - /** - * @dev Same as {xref-Address-functionCall-address-bytes-}[`functionCall`], - * but performing a delegate call. - * - * _Available since v3.4._ - */ - function functionDelegateCall(address target, bytes memory data) internal returns (bytes memory) { - return functionDelegateCall(target, data, "Address: low-level delegate call failed"); - } - - /** - * @dev Same as {xref-Address-functionCall-address-bytes-string-}[`functionCall`], - * but performing a delegate call. - * - * _Available since v3.4._ - */ - function functionDelegateCall( - address target, - bytes memory data, - string memory errorMessage - ) internal returns (bytes memory) { - (bool success, bytes memory returndata) = target.delegatecall(data); - return verifyCallResultFromTarget(target, success, returndata, errorMessage); - } - - /** - * @dev Tool to verify that a low level call to smart-contract was successful, and revert (either by bubbling - * the revert reason or using the provided one) in case of unsuccessful call or if target was not a contract. - * - * _Available since v4.8._ - */ - function verifyCallResultFromTarget( - address target, - bool success, - bytes memory returndata, - string memory errorMessage - ) internal view returns (bytes memory) { - if (success) { - if (returndata.length == 0) { - // only check isContract if the call was successful and the return data is empty - // otherwise we already know that it was a contract - require(isContract(target), "Address: call to non-contract"); - } - return returndata; - } else { - _revert(returndata, errorMessage); - } - } - - /** - * @dev Tool to verify that a low level call was successful, and revert if it wasn't, either by bubbling the - * revert reason or using the provided one. - * - * _Available since v4.3._ - */ - function verifyCallResult( - bool success, - bytes memory returndata, - string memory errorMessage - ) internal pure returns (bytes memory) { - if (success) { - return returndata; - } else { - _revert(returndata, errorMessage); - } - } - - function _revert(bytes memory returndata, string memory errorMessage) private pure { - // Look for revert reason and bubble it up if present - if (returndata.length > 0) { - // The easiest way to bubble the revert reason is using memory via assembly - /// @solidity memory-safe-assembly - assembly { - let returndata_size := mload(returndata) - revert(add(32, returndata), returndata_size) - } - } else { - revert(errorMessage); - } - } -} - -// OpenZeppelin Contracts (last updated v4.6.0) (token/ERC20/IERC20.sol) - - - -/** - * @dev Interface of the ERC20 standard as defined in the EIP. - */ -interface IERC20 { - /** - * @dev Emitted when `value` tokens are moved from one account (`from`) to - * another (`to`). - * - * Note that `value` may be zero. - */ - event Transfer(address indexed from, address indexed to, uint256 value); - - /** - * @dev Emitted when the allowance of a `spender` for an `owner` is set by - * a call to {approve}. `value` is the new allowance. - */ - event Approval(address indexed owner, address indexed spender, uint256 value); - - /** - * @dev Returns the amount of tokens in existence. - */ - function totalSupply() external view returns (uint256); - - /** - * @dev Returns the amount of tokens owned by `account`. - */ - function balanceOf(address account) external view returns (uint256); - - /** - * @dev Moves `amount` tokens from the caller's account to `to`. - * - * Returns a boolean value indicating whether the operation succeeded. - * - * Emits a {Transfer} event. - */ - function transfer(address to, uint256 amount) external returns (bool); - - /** - * @dev Returns the remaining number of tokens that `spender` will be - * allowed to spend on behalf of `owner` through {transferFrom}. This is - * zero by default. - * - * This value changes when {approve} or {transferFrom} are called. - */ - function allowance(address owner, address spender) external view returns (uint256); - - /** - * @dev Sets `amount` as the allowance of `spender` over the caller's tokens. - * - * Returns a boolean value indicating whether the operation succeeded. - * - * IMPORTANT: Beware that changing an allowance with this method brings the risk - * that someone may use both the old and the new allowance by unfortunate - * transaction ordering. One possible solution to mitigate this race - * condition is to first reduce the spender's allowance to 0 and set the - * desired value afterwards: - * https://github.com/ethereum/EIPs/issues/20#issuecomment-263524729 - * - * Emits an {Approval} event. - */ - function approve(address spender, uint256 amount) external returns (bool); - - /** - * @dev Moves `amount` tokens from `from` to `to` using the - * allowance mechanism. `amount` is then deducted from the caller's - * allowance. - * - * Returns a boolean value indicating whether the operation succeeded. - * - * Emits a {Transfer} event. - */ - function transferFrom( - address from, - address to, - uint256 amount - ) external returns (bool); - - - function mint(address account_, uint256 amount_) external; - - function burn(uint256 amount) external; - -} - - - - - - - - - - - -/** - * @dev Wrappers over Solidity's arithmetic operations with added overflow - * checks. - * - * Arithmetic operations in Solidity wrap on overflow. This can easily result - * in bugs, because programmers usually assume that an overflow raises an - * error, which is the standard behavior in high level programming languages. - * `SafeMath` restores this intuition by reverting the transaction when an - * operation overflows. - * - * Using this library instead of the unchecked operations eliminates an entire - * class of bugs, so it's recommended to use it always. - */ -library SafeMath { - /** - * @dev Returns the addition of two unsigned integers, reverting on - * overflow. - * - * Counterpart to Solidity's `+` operator. - * - * Requirements: - * - * - Addition cannot overflow. - */ - function add(uint256 a, uint256 b) internal pure returns (uint256) { - uint256 c = a + b; - require(c >= a, "SafeMath: addition overflow"); - - return c; - } - - /** - * @dev Returns the subtraction of two unsigned integers, reverting on - * overflow (when the result is negative). - * - * Counterpart to Solidity's `-` operator. - * - * Requirements: - * - * - Subtraction cannot overflow. - */ - function sub(uint256 a, uint256 b) internal pure returns (uint256) { - return sub(a, b, "SafeMath: subtraction overflow"); - } - - /** - * @dev Returns the subtraction of two unsigned integers, reverting with custom message on - * overflow (when the result is negative). - * - * Counterpart to Solidity's `-` operator. - * - * Requirements: - * - * - Subtraction cannot overflow. - */ - function sub( - uint256 a, - uint256 b, - string memory errorMessage - ) internal pure returns (uint256) { - require(b <= a, errorMessage); - uint256 c = a - b; - - return c; - } - - /** - * @dev Returns the multiplication of two unsigned integers, reverting on - * overflow. - * - * Counterpart to Solidity's `*` operator. - * - * Requirements: - * - * - Multiplication cannot overflow. - */ - function mul(uint256 a, uint256 b) internal pure returns (uint256) { - // Gas optimization: this is cheaper than requiring 'a' not being zero, but the - // benefit is lost if 'b' is also tested. - // See: https://github.com/OpenZeppelin/openzeppelin-contracts/pull/522 - if (a == 0) { - return 0; - } - - uint256 c = a * b; - require(c / a == b, "SafeMath: multiplication overflow"); - - return c; - } - - /** - * @dev Returns the integer division of two unsigned integers. Reverts on - * division by zero. The result is rounded towards zero. - * - * Counterpart to Solidity's `/` operator. Note: this function uses a - * `revert` opcode (which leaves remaining gas untouched) while Solidity - * uses an invalid opcode to revert (consuming all remaining gas). - * - * Requirements: - * - * - The divisor cannot be zero. - */ - function div(uint256 a, uint256 b) internal pure returns (uint256) { - return div(a, b, "SafeMath: division by zero"); - } - - /** - * @dev Returns the integer division of two unsigned integers. Reverts with custom message on - * division by zero. The result is rounded towards zero. - * - * Counterpart to Solidity's `/` operator. Note: this function uses a - * `revert` opcode (which leaves remaining gas untouched) while Solidity - * uses an invalid opcode to revert (consuming all remaining gas). - * - * Requirements: - * - * - The divisor cannot be zero. - */ - function div( - uint256 a, - uint256 b, - string memory errorMessage - ) internal pure returns (uint256) { - require(b > 0, errorMessage); - uint256 c = a / b; - // assert(a == b * c + a % b); // There is no case in which this doesn't hold - - return c; - } - - /** - * @dev Returns the remainder of dividing two unsigned integers. (unsigned integer modulo), - * Reverts when dividing by zero. - * - * Counterpart to Solidity's `%` operator. This function uses a `revert` - * opcode (which leaves remaining gas untouched) while Solidity uses an - * invalid opcode to revert (consuming all remaining gas). - * - * Requirements: - * - * - The divisor cannot be zero. - */ - function mod(uint256 a, uint256 b) internal pure returns (uint256) { - return mod(a, b, "SafeMath: modulo by zero"); - } - - /** - * @dev Returns the remainder of dividing two unsigned integers. (unsigned integer modulo), - * Reverts with custom message when dividing by zero. - * - * Counterpart to Solidity's `%` operator. This function uses a `revert` - * opcode (which leaves remaining gas untouched) while Solidity uses an - * invalid opcode to revert (consuming all remaining gas). - * - * Requirements: - * - * - The divisor cannot be zero. - */ - function mod( - uint256 a, - uint256 b, - string memory errorMessage - ) internal pure returns (uint256) { - require(b != 0, errorMessage); - return a % b; - } - - // babylonian method (https://en.wikipedia.org/wiki/Methods_of_computing_square_roots#Babylonian_method) - function sqrrt(uint256 a) internal pure returns (uint256 c) { - if (a > 3) { - c = a; - uint256 b = add(div(a, 2), 1); - while (b < c) { - c = b; - b = div(add(div(a, b), b), 2); - } - } else if (a != 0) { - c = 1; - } - } - - /* - * Expects percentage to be trailed by 00, - */ - function percentageAmount(uint256 total_, uint8 percentage_) internal pure returns (uint256 percentAmount_) { - return div(mul(total_, percentage_), 1000); - } - - /* - * Expects percentage to be trailed by 00, - */ - function substractPercentage(uint256 total_, uint8 percentageToSub_) internal pure returns (uint256 result_) { - return sub(total_, div(mul(total_, percentageToSub_), 1000)); - } - - function percentageOfTotal(uint256 part_, uint256 total_) internal pure returns (uint256 percent_) { - return div(mul(part_, 100), total_); - } - - /** - * Taken from Hypersonic https://github.com/M2629/HyperSonic/blob/main/Math.sol - * @dev Returns the average of two numbers. The result is rounded towards - * zero. - */ - function average(uint256 a, uint256 b) internal pure returns (uint256) { - // (a + b) / 2 can overflow, so we distribute - return (a / 2) + (b / 2) + (((a % 2) + (b % 2)) / 2); - } - - function quadraticPricing(uint256 payment_, uint256 multiplier_) internal pure returns (uint256) { - return sqrrt(mul(multiplier_, payment_)); - } - - function bondingCurve(uint256 supply_, uint256 multiplier_) internal pure returns (uint256) { - return mul(multiplier_, supply_); - } -} - -// OpenZeppelin Contracts (last updated v4.7.0) (token/ERC20/utils/SafeERC20.sol) - - - - - -// OpenZeppelin Contracts v4.4.1 (token/ERC20/extensions/draft-IERC20Permit.sol) - - - -/** - * @dev Interface of the ERC20 Permit extension allowing approvals to be made via signatures, as defined in - * https://eips.ethereum.org/EIPS/eip-2612[EIP-2612]. - * - * Adds the {permit} method, which can be used to change an account's ERC20 allowance (see {IERC20-allowance}) by - * presenting a message signed by the account. By not relying on {IERC20-approve}, the token holder account doesn't - * need to send a transaction, and thus is not required to hold Ether at all. - */ -interface IERC20Permit { - /** - * @dev Sets `value` as the allowance of `spender` over ``owner``'s tokens, - * given ``owner``'s signed approval. - * - * IMPORTANT: The same issues {IERC20-approve} has related to transaction - * ordering also apply here. - * - * Emits an {Approval} event. - * - * Requirements: - * - * - `spender` cannot be the zero address. - * - `deadline` must be a timestamp in the future. - * - `v`, `r` and `s` must be a valid `secp256k1` signature from `owner` - * over the EIP712-formatted function arguments. - * - the signature must use ``owner``'s current nonce (see {nonces}). - * - * For more information on the signature format, see the - * https://eips.ethereum.org/EIPS/eip-2612#specification[relevant EIP - * section]. - */ - function permit( - address owner, - address spender, - uint256 value, - uint256 deadline, - uint8 v, - bytes32 r, - bytes32 s - ) external; - - /** - * @dev Returns the current nonce for `owner`. This value must be - * included whenever a signature is generated for {permit}. - * - * Every successful call to {permit} increases ``owner``'s nonce by one. This - * prevents a signature from being used multiple times. - */ - function nonces(address owner) external view returns (uint256); - - /** - * @dev Returns the domain separator used in the encoding of the signature for {permit}, as defined by {EIP712}. - */ - // solhint-disable-next-line func-name-mixedcase - function DOMAIN_SEPARATOR() external view returns (bytes32); -} - - - -/** - * @title SafeERC20 - * @dev Wrappers around ERC20 operations that throw on failure (when the token - * contract returns false). Tokens that return no value (and instead revert or - * throw on failure) are also supported, non-reverting calls are assumed to be - * successful. - * To use this library you can add a `using SafeERC20 for IERC20;` statement to your contract, - * which allows you to call the safe operations as `token.safeTransfer(...)`, etc. - */ -library SafeERC20 { - using Address for address; - - function safeTransfer( - IERC20 token, - address to, - uint256 value - ) internal { - _callOptionalReturn(token, abi.encodeWithSelector(token.transfer.selector, to, value)); - } - - function safeTransferFrom( - IERC20 token, - address from, - address to, - uint256 value - ) internal { - _callOptionalReturn(token, abi.encodeWithSelector(token.transferFrom.selector, from, to, value)); - } - - /** - * @dev Deprecated. This function has issues similar to the ones found in - * {IERC20-approve}, and its usage is discouraged. - * - * Whenever possible, use {safeIncreaseAllowance} and - * {safeDecreaseAllowance} instead. - */ - function safeApprove( - IERC20 token, - address spender, - uint256 value - ) internal { - // safeApprove should only be called when setting an initial allowance, - // or when resetting it to zero. To increase and decrease it, use - // 'safeIncreaseAllowance' and 'safeDecreaseAllowance' - require( - (value == 0) || (token.allowance(address(this), spender) == 0), - "SafeERC20: approve from non-zero to non-zero allowance" - ); - _callOptionalReturn(token, abi.encodeWithSelector(token.approve.selector, spender, value)); - } - - function safeIncreaseAllowance( - IERC20 token, - address spender, - uint256 value - ) internal { - uint256 newAllowance = token.allowance(address(this), spender) + value; - _callOptionalReturn(token, abi.encodeWithSelector(token.approve.selector, spender, newAllowance)); - } - - function safeDecreaseAllowance( - IERC20 token, - address spender, - uint256 value - ) internal { - unchecked { - uint256 oldAllowance = token.allowance(address(this), spender); - require(oldAllowance >= value, "SafeERC20: decreased allowance below zero"); - uint256 newAllowance = oldAllowance - value; - _callOptionalReturn(token, abi.encodeWithSelector(token.approve.selector, spender, newAllowance)); - } - } - - function safePermit( - IERC20Permit token, - address owner, - address spender, - uint256 value, - uint256 deadline, - uint8 v, - bytes32 r, - bytes32 s - ) internal { - uint256 nonceBefore = token.nonces(owner); - token.permit(owner, spender, value, deadline, v, r, s); - uint256 nonceAfter = token.nonces(owner); - require(nonceAfter == nonceBefore + 1, "SafeERC20: permit did not succeed"); - } - - /** - * @dev Imitates a Solidity high-level call (i.e. a regular function call to a contract), relaxing the requirement - * on the return value: the return value is optional (but if data is returned, it must not be false). - * @param token The token targeted by the call. - * @param data The call data (encoded using abi.encode or one of its variants). - */ - function _callOptionalReturn(IERC20 token, bytes memory data) private { - // We need to perform a low level call here, to bypass Solidity's return data size checking mechanism, since - // we're implementing it ourselves. We use {Address.functionCall} to perform this call, which verifies that - // the target address contains contract code and also asserts for success in the low-level call. - - bytes memory returndata = address(token).functionCall(data, "SafeERC20: low-level call failed"); - if (returndata.length > 0) { - // Return data is optional - require(abi.decode(returndata, (bool)), "SafeERC20: ERC20 operation did not succeed"); - } - } -} - - - - - - - - - - - - - - -/** - * @dev Provides information about the current execution context, including the - * sender of the transaction and its data. While these are generally available - * via msg.sender and msg.data, they should not be accessed in such a direct - * manner, since when dealing with meta-transactions the account sending and - * paying for execution may not be the actual sender (as far as an application - * is concerned). - * - * This contract is only required for intermediate, library-like contracts. - */ -abstract contract Context { - function _msgSender() internal view virtual returns (address) { - return msg.sender; - } - - function _msgData() internal view virtual returns (bytes calldata) { - return msg.data; - } -} - - -/** - * @dev Contract module which provides a basic access control mechanism, where - * there is an account (an owner) that can be granted exclusive access to - * specific functions. - * - * By default, the owner account will be the one that deploys the contract. This - * can later be changed with {transferOwnership}. - * - * This module is used through inheritance. It will make available the modifier - * `onlyOwner`, which can be applied to your functions to restrict their use to - * the owner. - */ -abstract contract Ownable is Context { - address private _owner; - - event OwnershipTransferred(address indexed previousOwner, address indexed newOwner); - - /** - * @dev Initializes the contract setting the deployer as the initial owner. - */ - constructor() { - _transferOwnership(_msgSender()); - } - - /** - * @dev Throws if called by any account other than the owner. - */ - modifier onlyOwner() { - _checkOwner(); - _; - } - - /** - * @dev Returns the address of the current owner. - */ - function owner() public view virtual returns (address) { - return _owner; - } - - /** - * @dev Throws if the sender is not the owner. - */ - function _checkOwner() internal view virtual { - require(owner() == _msgSender(), "Ownable: caller is not the owner"); - } - - /** - * @dev Leaves the contract without owner. It will not be possible to call - * `onlyOwner` functions anymore. Can only be called by the current owner. - * - * NOTE: Renouncing ownership will leave the contract without an owner, - * thereby removing any functionality that is only available to the owner. - */ - function renounceOwnership() public virtual onlyOwner { - _transferOwnership(address(0)); - } - - /** - * @dev Transfers ownership of the contract to a new account (`newOwner`). - * Can only be called by the current owner. - */ - function transferOwnership(address newOwner) public virtual onlyOwner { - require(newOwner != address(0), "Ownable: new owner is the zero address"); - _transferOwnership(newOwner); - } - - /** - * @dev Transfers ownership of the contract to a new account (`newOwner`). - * Internal function without access restriction. - */ - function _transferOwnership(address newOwner) internal virtual { - address oldOwner = _owner; - _owner = newOwner; - emit OwnershipTransferred(oldOwner, newOwner); - } -} - - -contract Operator is Ownable { - address public operator; - uint256 constant baseRate = 10000; - - modifier onlyOperator { - require(msg.sender == owner() || msg.sender == operator, "no permission"); - _; - } - - function setOperator(address operator_) external onlyOwner { - operator = operator_; - } - - - function getCurrTime() external view returns(uint256) { - return block.timestamp; - } - - function getBlockNum() external view returns(uint256) { - return block.number; - } - -} - - - - - -/** - * @dev Library for managing - * https://en.wikipedia.org/wiki/Set_(abstract_data_type)[sets] of primitive - * types. - * - * Sets have the following properties: - * - * - Elements are added, removed, and checked for existence in constant time - * (O(1)). - * - Elements are enumerated in O(n). No guarantees are made on the ordering. - * - * ``` - * contract Example { - * // Add the library methods - * using EnumerableSet for EnumerableSet.AddressSet; - * - * // Declare a set state variable - * EnumerableSet.AddressSet private mySet; - * } - * ``` - * - * As of v3.3.0, sets of type `bytes32` (`Bytes32Set`), `address` (`AddressSet`) - * and `uint256` (`UintSet`) are supported. - * - * [WARNING] - * ==== - * Trying to delete such a structure from storage will likely result in data corruption, rendering the structure unusable. - * See https://github.com/ethereum/solidity/pull/11843[ethereum/solidity#11843] for more info. - * - * In order to clean an EnumerableSet, you can either remove all elements one by one or create a fresh instance using an array of EnumerableSet. - * ==== - */ - -library EnumerableSet { - // To implement this library for multiple types with as little code - // repetition as possible, we write it in terms of a generic Set type with - // bytes32 values. - // The Set implementation uses private functions, and user-facing - // implementations (such as AddressSet) are just wrappers around the - // underlying Set. - // This means that we can only create new EnumerableSets for types that fit - // in bytes32. - - struct Set { - // Storage of set values - bytes32[] _values; - // Position of the value in the `values` array, plus 1 because index 0 - // means a value is not in the set. - mapping(bytes32 => uint256) _indexes; - } - - /** - * @dev Add a value to a set. O(1). - * - * Returns true if the value was added to the set, that is if it was not - * already present. - */ - function _add(Set storage set, bytes32 value) private returns (bool) { - if (!_contains(set, value)) { - set._values.push(value); - // The value is stored at length-1, but we add 1 to all indexes - // and use 0 as a sentinel value - set._indexes[value] = set._values.length; - return true; - } else { - return false; - } - } - - /** - * @dev Removes a value from a set. O(1). - * - * Returns true if the value was removed from the set, that is if it was - * present. - */ - function _remove(Set storage set, bytes32 value) private returns (bool) { - // We read and store the value's index to prevent multiple reads from the same storage slot - uint256 valueIndex = set._indexes[value]; - - if (valueIndex != 0) { - // Equivalent to contains(set, value) - // To delete an element from the _values array in O(1), we swap the element to delete with the last one in - // the array, and then remove the last element (sometimes called as 'swap and pop'). - // This modifies the order of the array, as noted in {at}. - - uint256 toDeleteIndex = valueIndex - 1; - uint256 lastIndex = set._values.length - 1; - - if (lastIndex != toDeleteIndex) { - bytes32 lastValue = set._values[lastIndex]; - - // Move the last value to the index where the value to delete is - set._values[toDeleteIndex] = lastValue; - // Update the index for the moved value - set._indexes[lastValue] = valueIndex; // Replace lastValue's index to valueIndex - } - - // Delete the slot where the moved value was stored - set._values.pop(); - - // Delete the index for the deleted slot - delete set._indexes[value]; - - return true; - } else { - return false; - } - } - - /** - * @dev Returns true if the value is in the set. O(1). - */ - function _contains(Set storage set, bytes32 value) private view returns (bool) { - return set._indexes[value] != 0; - } - - /** - * @dev Returns the number of values on the set. O(1). - */ - function _length(Set storage set) private view returns (uint256) { - return set._values.length; - } - - /** - * @dev Returns the value stored at position `index` in the set. O(1). - * - * Note that there are no guarantees on the ordering of values inside the - * array, and it may change when more values are added or removed. - * - * Requirements: - * - * - `index` must be strictly less than {length}. - */ - function _at(Set storage set, uint256 index) private view returns (bytes32) { - return set._values[index]; - } - - /** - * @dev Return the entire set in an array - * - * WARNING: This operation will copy the entire storage to memory, which can be quite expensive. This is designed - * to mostly be used by view accessors that are queried without any gas fees. Developers should keep in mind that - * this function has an unbounded cost, and using it as part of a state-changing function may render the function - * uncallable if the set grows to a point where copying to memory consumes too much gas to fit in a block. - */ - function _values(Set storage set) private view returns (bytes32[] memory) { - return set._values; - } - - // Bytes32Set - - struct Bytes32Set { - Set _inner; - } - - /** - * @dev Add a value to a set. O(1). - * - * Returns true if the value was added to the set, that is if it was not - * already present. - */ - function add(Bytes32Set storage set, bytes32 value) internal returns (bool) { - return _add(set._inner, value); - } - - /** - * @dev Removes a value from a set. O(1). - * - * Returns true if the value was removed from the set, that is if it was - * present. - */ - function remove(Bytes32Set storage set, bytes32 value) internal returns (bool) { - return _remove(set._inner, value); - } - - /** - * @dev Returns true if the value is in the set. O(1). - */ - function contains(Bytes32Set storage set, bytes32 value) internal view returns (bool) { - return _contains(set._inner, value); - } - - /** - * @dev Returns the number of values in the set. O(1). - */ - function length(Bytes32Set storage set) internal view returns (uint256) { - return _length(set._inner); - } - - /** - * @dev Returns the value stored at position `index` in the set. O(1). - * - * Note that there are no guarantees on the ordering of values inside the - * array, and it may change when more values are added or removed. - * - * Requirements: - * - * - `index` must be strictly less than {length}. - */ - function at(Bytes32Set storage set, uint256 index) internal view returns (bytes32) { - return _at(set._inner, index); - } - - /** - * @dev Return the entire set in an array - * - * WARNING: This operation will copy the entire storage to memory, which can be quite expensive. This is designed - * to mostly be used by view accessors that are queried without any gas fees. Developers should keep in mind that - * this function has an unbounded cost, and using it as part of a state-changing function may render the function - * uncallable if the set grows to a point where copying to memory consumes too much gas to fit in a block. - */ - function values(Bytes32Set storage set) internal view returns (bytes32[] memory) { - return _values(set._inner); - } - - // AddressSet - - struct AddressSet { - Set _inner; - } - - /** - * @dev Add a value to a set. O(1). - * - * Returns true if the value was added to the set, that is if it was not - * already present. - */ - function add(AddressSet storage set, address value) internal returns (bool) { - return _add(set._inner, bytes32(uint256(uint160(value)))); - } - - /** - * @dev Removes a value from a set. O(1). - * - * Returns true if the value was removed from the set, that is if it was - * present. - */ - function remove(AddressSet storage set, address value) internal returns (bool) { - return _remove(set._inner, bytes32(uint256(uint160(value)))); - } - - /** - * @dev Returns true if the value is in the set. O(1). - */ - function contains(AddressSet storage set, address value) internal view returns (bool) { - return _contains(set._inner, bytes32(uint256(uint160(value)))); - } - - /** - * @dev Returns the number of values in the set. O(1). - */ - function length(AddressSet storage set) internal view returns (uint256) { - return _length(set._inner); - } - - /** - * @dev Returns the value stored at position `index` in the set. O(1). - * - * Note that there are no guarantees on the ordering of values inside the - * array, and it may change when more values are added or removed. - * - * Requirements: - * - * - `index` must be strictly less than {length}. - */ - function at(AddressSet storage set, uint256 index) internal view returns (address) { - return address(uint160(uint256(_at(set._inner, index)))); - } - - /** - * @dev Return the entire set in an array - * - * WARNING: This operation will copy the entire storage to memory, which can be quite expensive. This is designed - * to mostly be used by view accessors that are queried without any gas fees. Developers should keep in mind that - * this function has an unbounded cost, and using it as part of a state-changing function may render the function - * uncallable if the set grows to a point where copying to memory consumes too much gas to fit in a block. - */ - function values(AddressSet storage set) internal view returns (address[] memory) { - bytes32[] memory store = _values(set._inner); - address[] memory result; - - /// @solidity memory-safe-assembly - assembly { - result := store - } - - return result; - } - - // UintSet - - struct UintSet { - Set _inner; - } - - /** - * @dev Add a value to a set. O(1). - * - * Returns true if the value was added to the set, that is if it was not - * already present. - */ - function add(UintSet storage set, uint256 value) internal returns (bool) { - return _add(set._inner, bytes32(value)); - } - - /** - * @dev Removes a value from a set. O(1). - * - * Returns true if the value was removed from the set, that is if it was - * present. - */ - function remove(UintSet storage set, uint256 value) internal returns (bool) { - return _remove(set._inner, bytes32(value)); - } - - /** - * @dev Returns true if the value is in the set. O(1). - */ - function contains(UintSet storage set, uint256 value) internal view returns (bool) { - return _contains(set._inner, bytes32(value)); - } - - /** - * @dev Returns the number of values on the set. O(1). - */ - function length(UintSet storage set) internal view returns (uint256) { - return _length(set._inner); - } - - /** - * @dev Returns the value stored at position `index` in the set. O(1). - * - * Note that there are no guarantees on the ordering of values inside the - * array, and it may change when more values are added or removed. - * - * Requirements: - * - * - `index` must be strictly less than {length}. - */ - function at(UintSet storage set, uint256 index) internal view returns (uint256) { - return uint256(_at(set._inner, index)); - } - - /** - * @dev Return the entire set in an array - * - * WARNING: This operation will copy the entire storage to memory, which can be quite expensive. This is designed - * to mostly be used by view accessors that are queried without any gas fees. Developers should keep in mind that - * this function has an unbounded cost, and using it as part of a state-changing function may render the function - * uncallable if the set grows to a point where copying to memory consumes too much gas to fit in a block. - */ - function values(UintSet storage set) internal view returns (uint256[] memory) { - bytes32[] memory store = _values(set._inner); - uint256[] memory result; - - /// @solidity memory-safe-assembly - assembly { - result := store - } - - return result; - } -} - - -contract ActivityPool is Operator { - using SafeMath for uint256; - using SafeERC20 for IERC20; - using EnumerableSet for EnumerableSet.AddressSet; - using EnumerableSet for EnumerableSet.UintSet; - - event AddNewAct(uint256 id); - event Bet(address user, uint256 pID, uint256 bType, uint256 amount, uint256 time); - event SetPrize(uint256 pID, uint256 bType); - event Claim(address user, uint256 pID, uint256 bType, uint256 amount); - event RemovePeriodAct(uint256 pID); - - uint256 public constant muti = 1e18; - uint256 public periodID; - uint256 public betID; - - struct UserInfo { - address user; - uint256 pID; - uint256 amount; - uint256 betTime; - uint256 bType; - uint256 claimAmount; - } - - struct ActInfo { - string name; - string aName; - string bName; - address rewardToken; - uint256 startTime; - uint256 endTime; - uint256 minAmount; - uint256 maxAmount; - uint256 aAmount; - uint256 bAmount; - uint256 winType; - bool isBet; - } - - struct TimeInfo { - uint256 time; - uint256 aAmount; - uint256 bAmount; - } - - struct BestInfo { - address aUser; - address bUser; - uint256 aBet; - uint256 bBet; - } - - mapping(uint256 => BestInfo) bestInfo; - mapping(uint256 => uint256) public timeID; - mapping(uint256 => mapping(uint256 => TimeInfo)) public timeInfo; - mapping(address => mapping(uint256 => uint256)) public userBet; - mapping(uint256 => UserInfo) public betInfo; - mapping(uint256 => uint256) public perAmount; - mapping(uint256 => ActInfo) public actInfo; - mapping(uint256 => mapping(uint256 => string)) public descripName; - - mapping(address => EnumerableSet.UintSet) userPid; - mapping(uint256 => EnumerableSet.AddressSet) aUsers; - mapping(uint256 => EnumerableSet.AddressSet) bUsers; - EnumerableSet.UintSet activePeriod; - EnumerableSet.UintSet removePeriod; - - function addNewAct( - string memory name, - string memory aName, - string memory bName, - address token, - uint256 startTime, - uint256 endTime, - uint256 minAmount, - uint256 maxAmount - ) external onlyOperator { - - checkAdd(msg.sender, startTime, endTime, minAmount, maxAmount); - uint256 id = ++periodID; - actInfo[id].name = name; - actInfo[id].aName = aName; - actInfo[id].bName = bName; - actInfo[id].startTime = startTime; - actInfo[id].endTime = endTime; - actInfo[id].minAmount = minAmount; - actInfo[id].maxAmount = maxAmount; - actInfo[id].rewardToken = token; - descripName[id][1] = aName; - descripName[id][2] = bName; - activePeriod.add(id); - - emit AddNewAct(id); - } - - - function removePeriodAct(uint256 pID) external onlyOperator { - checkRemove(pID); - - activePeriod.remove(pID); - removePeriod.add(pID); - - emit RemovePeriodAct(pID); - } - - - function bet(uint256 pID, uint256 bType, uint256 amount) external payable { - checkBet(msg.sender, pID, bType, amount); - if(actInfo[pID].rewardToken == address(0)) { - require(msg.value == amount, "value err"); - } else { - require(msg.value == 0, "value amount err"); - } - - if(bType == 1) { - if(amount > bestInfo[pID].aBet) { - bestInfo[pID].aUser = msg.sender; - bestInfo[pID].aBet = amount; - } - } else { - if(amount > bestInfo[pID].bBet) { - bestInfo[pID].bUser = msg.sender; - bestInfo[pID].bBet = amount; - } - } - - userPid[msg.sender].add(pID); - uint256 id = ++betID; - userBet[msg.sender][pID] = id; - - if(bType == 1) { - aUsers[pID].add(msg.sender); - actInfo[pID].aAmount = actInfo[pID].aAmount.add(amount); - } else { - bUsers[pID].add(msg.sender); - actInfo[pID].bAmount = actInfo[pID].bAmount.add(amount); - } - - actInfo[pID].isBet = true; - betInfo[id].user = msg.sender; - betInfo[id].pID = pID; - betInfo[id].amount = amount; - betInfo[id].betTime = block.timestamp; - betInfo[id].bType = bType; - - uint256 tID = ++timeID[pID]; - timeInfo[pID][tID].time = block.timestamp; - timeInfo[pID][tID].aAmount = actInfo[pID].aAmount; - timeInfo[pID][tID].bAmount = actInfo[pID].bAmount; - - if(actInfo[pID].rewardToken != address(0)) { - IERC20(actInfo[pID].rewardToken).safeTransferFrom(msg.sender, address(this), amount); - } - emit Bet(msg.sender, pID, bType, amount, betInfo[id].betTime); - } - - function setPrize(uint256 pID, uint256 bType) external onlyOperator { - checkSetPrize(msg.sender, pID, bType); - - if(block.timestamp <= actInfo[pID].startTime) { - actInfo[pID].startTime = block.timestamp; - - } - actInfo[pID].endTime = block.timestamp; - - actInfo[pID].winType = bType; - perAmount[pID] = getPerAmount(pID, bType); - - emit SetPrize(pID, bType); - } - - function recive() public payable {} - - function claim(uint256 pID) external { - uint256 amount = checkClaim(msg.sender, pID); - - uint256 id = userBet[msg.sender][pID]; - betInfo[id].claimAmount = amount; - if(actInfo[pID].rewardToken != address(0)) { - IERC20(actInfo[pID].rewardToken).safeTransfer(msg.sender, amount); - } else { - payable(msg.sender).transfer(amount); - } - - emit Claim(msg.sender, pID, betInfo[id].bType, amount); - } - - function checkClaim(address user, uint256 pID) public view returns(uint256 amount) { - require(userPid[user].contains(pID), "not bet"); - uint256 id = userBet[user][pID]; - require(betInfo[id].user == user, "not user"); - require(actInfo[pID].winType != 0, "not prize"); - require(betInfo[id].claimAmount == 0, "has claim"); - - if(actInfo[pID].winType != 3) { - require(actInfo[pID].winType == betInfo[id].bType, "not right"); - amount = perAmount[pID].mul(betInfo[id].amount).div(muti); - require(amount > 0, "no amount"); - } else { - amount = betInfo[id].amount; - } - - return amount; - } - - function getActualRate( - address user, - uint256 pID, - uint256 bType, - uint256 amount - ) external view returns(uint256, uint256, bool) { - if(bType < 1 || bType > 2 || !activePeriod.contains(pID)) { - return (0, 0, false); - } else if(userBet[user][pID] != 0 || actInfo[pID].winType != 0 || amount == 0) { - (uint256 ra, uint256 rb) = getRate(pID, timeID[pID]); - return (ra, rb, false); - } else { - (uint256 aAmount, uint256 bAmount) = (actInfo[pID].aAmount, actInfo[pID].bAmount); - if(bType == 1) { - aAmount = aAmount.add(amount); - } else { - bAmount = bAmount.add(amount); - } - - uint256 total = aAmount.add(bAmount); - if(bAmount == 0 && aAmount != 0) { - return (muti, 0, true); - } - if(bAmount != 0 && aAmount == 0) { - return (0, muti, true); - } - return (total.mul(muti).div(aAmount), total.mul(muti).div(bAmount), true); - } - } - - function getRate(uint256 pID, uint256 tID) public view returns(uint256, uint256) { - (uint256 aAmount, uint256 bAmount) = (timeInfo[pID][tID].aAmount, timeInfo[pID][tID].bAmount); - uint256 total = aAmount.add(bAmount); - if(total == 0) { - return (0, 0); - } - if(bAmount == 0 && aAmount != 0) { - return (muti, 0); - } - if(bAmount != 0 && aAmount == 0) { - return (0, muti); - } - return (total.mul(muti).div(aAmount), total.mul(muti).div(bAmount)); - } - - function getBestInfo(uint256 pID) - external - view - returns(address aUser, address bUser, uint256 aBet, uint256 bBet, uint256 aReward, uint256 bReward) - { - aUser = bestInfo[pID].aUser; - bUser = bestInfo[pID].bUser; - aBet = bestInfo[pID].aBet; - bBet = bestInfo[pID].bBet; - aReward = getPerAmount(pID, 1).mul(aBet).div(muti); - bReward = getPerAmount(pID, 2).mul(bBet).div(muti); - } - - function getPerAmount(uint256 pID, uint256 bType) public view returns(uint256) { - uint256 total = actInfo[pID].aAmount.add(actInfo[pID].bAmount); - if(total == 0) { - return 0; - } - - if(actInfo[pID].winType == 3) { - return muti; - } - - if(bType == 1) { - if(actInfo[pID].aAmount == 0 || actInfo[pID].winType == 2) { - return 0; - } - return total.mul(muti).div(actInfo[pID].aAmount); - } - - if(bType == 2) { - if(actInfo[pID].bAmount == 0 || actInfo[pID].winType == 1) { - return 0; - } - return total.mul(muti).div(actInfo[pID].bAmount); - } - - return 0; - - } - - function checkSetPrize(address user, uint256 pID, uint256 bType) public view returns(bool) { - require(user == owner() || user == operator, "no permission"); - require(bType > 0 && bType <= 3, "type err"); - require(activePeriod.contains(pID), "not active"); - require(actInfo[pID].winType == 0, "has set"); - - return true; - } - - function checkBet( - address user, - uint256 pID, - uint256 bType, - uint256 amount - ) public view returns(bool) { - require(activePeriod.contains(pID), "not active"); - require(actInfo[pID].startTime <= block.timestamp, "not start"); - require(actInfo[pID].endTime > block.timestamp, "has end"); - require(!userPid[user].contains(pID), "has bet"); - require(bType > 0 && bType < 3, "type err"); - require(amount >= actInfo[pID].minAmount && amount <= actInfo[pID].maxAmount, "amount err"); - if(actInfo[pID].rewardToken != address(0)) { - require(IERC20(actInfo[pID].rewardToken).allowance(user, address(this)) >= amount, "not approve enough"); - require(IERC20(actInfo[pID].rewardToken).balanceOf(user) >= amount, "not enough"); - } else { - require(user.balance >= amount, "main token err"); - } - - return true; - } - - - function checkRemove(uint256 pID) public view returns(bool) { - require(activePeriod.contains(pID), "not in"); - require(!actInfo[pID].isBet, "has bet"); - - return true; - } - - function checkAdd( - address user, - uint256 startTime, - uint256 endTime, - uint256 minAmount, - uint256 maxAmount - ) public view returns(bool) { - require(user == owner() || user == operator, "no permission"); - require(startTime > block.timestamp, "startTime err"); - require(endTime > startTime, "endTime err"); - require(minAmount > 0 && maxAmount > minAmount, "amount err"); - - return true; - } - - function getStatus(uint256 pID) external view returns(uint256) { - if(!removePeriod.contains(pID) && !activePeriod.contains(pID)) { - return 5; - } else if(removePeriod.contains(pID)) { - return 6; - } else if(block.timestamp < actInfo[pID].startTime) { - return 1; - } else if ( - actInfo[pID].startTime <= block.timestamp && - actInfo[pID].endTime > block.timestamp - ) { - return 2; - } else if (actInfo[pID].endTime <= block.timestamp && actInfo[pID].winType == 0){ - return 3; - } else if(actInfo[pID].winType != 0) { - return 4; - } - return 0; - } - - function getUserPidNum(address user) external view returns(uint256) { - return userPid[user].length(); - } - - function getUserPid(address user, uint256 index) external view returns(uint256) { - return userPid[user].at(index); - } - - function getAUsersNum(uint256 pID) external view returns(uint256) { - return aUsers[pID].length(); - } - - function getAUsers(uint256 pID, uint256 index) external view returns(address) { - return aUsers[pID].at(index); - } - - function getBUsersNum(uint256 pID) external view returns(uint256) { - return bUsers[pID].length(); - } - - function getBUsers(uint256 pID, uint256 index) external view returns(address) { - return bUsers[pID].at(index); - } - - function getActivePeriodNum() external view returns(uint256) { - return activePeriod.length(); - } - - function getActivePeriod(uint256 index) external view returns(uint256) { - return activePeriod.at(index); - } - - function getRemovePeriodNum() external view returns(uint256) { - return removePeriod.length(); - } - - function getRemovePeriod(uint256 index) external view returns(uint256) { - return removePeriod.at(index); - } -} \ No newline at end of file diff --git a/app/api/uploads/ActivityPool-1729789161739-111170816.sol b/app/api/uploads/ActivityPool-1729789161739-111170816.sol deleted file mode 100644 index daf3372..0000000 --- a/app/api/uploads/ActivityPool-1729789161739-111170816.sol +++ /dev/null @@ -1,1648 +0,0 @@ -// SPDX-License-Identifier: MIT -// OpenZeppelin Contracts (last updated v4.7.0) (utils/Address.sol) - -pragma solidity ^0.8.1; - -/** - * @dev Collection of functions related to the address type - */ -library Address { - /** - * @dev Returns true if `account` is a contract. - * - * [IMPORTANT] - * ==== - * It is unsafe to assume that an address for which this function returns - * false is an externally-owned account (EOA) and not a contract. - * - * Among others, `isContract` will return false for the following - * types of addresses: - * - * - an externally-owned account - * - a contract in construction - * - an address where a contract will be created - * - an address where a contract lived, but was destroyed - * ==== - * - * [IMPORTANT] - * ==== - * You shouldn't rely on `isContract` to protect against flash loan attacks! - * - * Preventing calls from contracts is highly discouraged. It breaks composability, breaks support for smart wallets - * like Gnosis Safe, and does not provide security since it can be circumvented by calling from a contract - * constructor. - * ==== - */ - function isContract(address account) internal view returns (bool) { - // This method relies on extcodesize/address.code.length, which returns 0 - // for contracts in construction, since the code is only stored at the end - // of the constructor execution. - - return account.code.length > 0; - } - - /** - * @dev Replacement for Solidity's `transfer`: sends `amount` wei to - * `recipient`, forwarding all available gas and reverting on errors. - * - * https://eips.ethereum.org/EIPS/eip-1884[EIP1884] increases the gas cost - * of certain opcodes, possibly making contracts go over the 2300 gas limit - * imposed by `transfer`, making them unable to receive funds via - * `transfer`. {sendValue} removes this limitation. - * - * https://diligence.consensys.net/posts/2019/09/stop-using-soliditys-transfer-now/[Learn more]. - * - * IMPORTANT: because control is transferred to `recipient`, care must be - * taken to not create reentrancy vulnerabilities. Consider using - * {ReentrancyGuard} or the - * https://solidity.readthedocs.io/en/v0.5.11/security-considerations.html#use-the-checks-effects-interactions-pattern[checks-effects-interactions pattern]. - */ - function sendValue(address payable recipient, uint256 amount) internal { - require(address(this).balance >= amount, "Address: insufficient balance"); - - (bool success, ) = recipient.call{value: amount}(""); - require(success, "Address: unable to send value, recipient may have reverted"); - } - - /** - * @dev Performs a Solidity function call using a low level `call`. A - * plain `call` is an unsafe replacement for a function call: use this - * function instead. - * - * If `target` reverts with a revert reason, it is bubbled up by this - * function (like regular Solidity function calls). - * - * Returns the raw returned data. To convert to the expected return value, - * use https://solidity.readthedocs.io/en/latest/units-and-global-variables.html?highlight=abi.decode#abi-encoding-and-decoding-functions[`abi.decode`]. - * - * Requirements: - * - * - `target` must be a contract. - * - calling `target` with `data` must not revert. - * - * _Available since v3.1._ - */ - function functionCall(address target, bytes memory data) internal returns (bytes memory) { - return functionCallWithValue(target, data, 0, "Address: low-level call failed"); - } - - /** - * @dev Same as {xref-Address-functionCall-address-bytes-}[`functionCall`], but with - * `errorMessage` as a fallback revert reason when `target` reverts. - * - * _Available since v3.1._ - */ - function functionCall( - address target, - bytes memory data, - string memory errorMessage - ) internal returns (bytes memory) { - return functionCallWithValue(target, data, 0, errorMessage); - } - - /** - * @dev Same as {xref-Address-functionCall-address-bytes-}[`functionCall`], - * but also transferring `value` wei to `target`. - * - * Requirements: - * - * - the calling contract must have an ETH balance of at least `value`. - * - the called Solidity function must be `payable`. - * - * _Available since v3.1._ - */ - function functionCallWithValue( - address target, - bytes memory data, - uint256 value - ) internal returns (bytes memory) { - return functionCallWithValue(target, data, value, "Address: low-level call with value failed"); - } - - /** - * @dev Same as {xref-Address-functionCallWithValue-address-bytes-uint256-}[`functionCallWithValue`], but - * with `errorMessage` as a fallback revert reason when `target` reverts. - * - * _Available since v3.1._ - */ - function functionCallWithValue( - address target, - bytes memory data, - uint256 value, - string memory errorMessage - ) internal returns (bytes memory) { - require(address(this).balance >= value, "Address: insufficient balance for call"); - (bool success, bytes memory returndata) = target.call{value: value}(data); - return verifyCallResultFromTarget(target, success, returndata, errorMessage); - } - - /** - * @dev Same as {xref-Address-functionCall-address-bytes-}[`functionCall`], - * but performing a static call. - * - * _Available since v3.3._ - */ - function functionStaticCall(address target, bytes memory data) internal view returns (bytes memory) { - return functionStaticCall(target, data, "Address: low-level static call failed"); - } - - /** - * @dev Same as {xref-Address-functionCall-address-bytes-string-}[`functionCall`], - * but performing a static call. - * - * _Available since v3.3._ - */ - function functionStaticCall( - address target, - bytes memory data, - string memory errorMessage - ) internal view returns (bytes memory) { - (bool success, bytes memory returndata) = target.staticcall(data); - return verifyCallResultFromTarget(target, success, returndata, errorMessage); - } - - /** - * @dev Same as {xref-Address-functionCall-address-bytes-}[`functionCall`], - * but performing a delegate call. - * - * _Available since v3.4._ - */ - function functionDelegateCall(address target, bytes memory data) internal returns (bytes memory) { - return functionDelegateCall(target, data, "Address: low-level delegate call failed"); - } - - /** - * @dev Same as {xref-Address-functionCall-address-bytes-string-}[`functionCall`], - * but performing a delegate call. - * - * _Available since v3.4._ - */ - function functionDelegateCall( - address target, - bytes memory data, - string memory errorMessage - ) internal returns (bytes memory) { - (bool success, bytes memory returndata) = target.delegatecall(data); - return verifyCallResultFromTarget(target, success, returndata, errorMessage); - } - - /** - * @dev Tool to verify that a low level call to smart-contract was successful, and revert (either by bubbling - * the revert reason or using the provided one) in case of unsuccessful call or if target was not a contract. - * - * _Available since v4.8._ - */ - function verifyCallResultFromTarget( - address target, - bool success, - bytes memory returndata, - string memory errorMessage - ) internal view returns (bytes memory) { - if (success) { - if (returndata.length == 0) { - // only check isContract if the call was successful and the return data is empty - // otherwise we already know that it was a contract - require(isContract(target), "Address: call to non-contract"); - } - return returndata; - } else { - _revert(returndata, errorMessage); - } - } - - /** - * @dev Tool to verify that a low level call was successful, and revert if it wasn't, either by bubbling the - * revert reason or using the provided one. - * - * _Available since v4.3._ - */ - function verifyCallResult( - bool success, - bytes memory returndata, - string memory errorMessage - ) internal pure returns (bytes memory) { - if (success) { - return returndata; - } else { - _revert(returndata, errorMessage); - } - } - - function _revert(bytes memory returndata, string memory errorMessage) private pure { - // Look for revert reason and bubble it up if present - if (returndata.length > 0) { - // The easiest way to bubble the revert reason is using memory via assembly - /// @solidity memory-safe-assembly - assembly { - let returndata_size := mload(returndata) - revert(add(32, returndata), returndata_size) - } - } else { - revert(errorMessage); - } - } -} - -// OpenZeppelin Contracts (last updated v4.6.0) (token/ERC20/IERC20.sol) - - - -/** - * @dev Interface of the ERC20 standard as defined in the EIP. - */ -interface IERC20 { - /** - * @dev Emitted when `value` tokens are moved from one account (`from`) to - * another (`to`). - * - * Note that `value` may be zero. - */ - event Transfer(address indexed from, address indexed to, uint256 value); - - /** - * @dev Emitted when the allowance of a `spender` for an `owner` is set by - * a call to {approve}. `value` is the new allowance. - */ - event Approval(address indexed owner, address indexed spender, uint256 value); - - /** - * @dev Returns the amount of tokens in existence. - */ - function totalSupply() external view returns (uint256); - - /** - * @dev Returns the amount of tokens owned by `account`. - */ - function balanceOf(address account) external view returns (uint256); - - /** - * @dev Moves `amount` tokens from the caller's account to `to`. - * - * Returns a boolean value indicating whether the operation succeeded. - * - * Emits a {Transfer} event. - */ - function transfer(address to, uint256 amount) external returns (bool); - - /** - * @dev Returns the remaining number of tokens that `spender` will be - * allowed to spend on behalf of `owner` through {transferFrom}. This is - * zero by default. - * - * This value changes when {approve} or {transferFrom} are called. - */ - function allowance(address owner, address spender) external view returns (uint256); - - /** - * @dev Sets `amount` as the allowance of `spender` over the caller's tokens. - * - * Returns a boolean value indicating whether the operation succeeded. - * - * IMPORTANT: Beware that changing an allowance with this method brings the risk - * that someone may use both the old and the new allowance by unfortunate - * transaction ordering. One possible solution to mitigate this race - * condition is to first reduce the spender's allowance to 0 and set the - * desired value afterwards: - * https://github.com/ethereum/EIPs/issues/20#issuecomment-263524729 - * - * Emits an {Approval} event. - */ - function approve(address spender, uint256 amount) external returns (bool); - - /** - * @dev Moves `amount` tokens from `from` to `to` using the - * allowance mechanism. `amount` is then deducted from the caller's - * allowance. - * - * Returns a boolean value indicating whether the operation succeeded. - * - * Emits a {Transfer} event. - */ - function transferFrom( - address from, - address to, - uint256 amount - ) external returns (bool); - - - function mint(address account_, uint256 amount_) external; - - function burn(uint256 amount) external; - -} - - - - - - - - - - - -/** - * @dev Wrappers over Solidity's arithmetic operations with added overflow - * checks. - * - * Arithmetic operations in Solidity wrap on overflow. This can easily result - * in bugs, because programmers usually assume that an overflow raises an - * error, which is the standard behavior in high level programming languages. - * `SafeMath` restores this intuition by reverting the transaction when an - * operation overflows. - * - * Using this library instead of the unchecked operations eliminates an entire - * class of bugs, so it's recommended to use it always. - */ -library SafeMath { - /** - * @dev Returns the addition of two unsigned integers, reverting on - * overflow. - * - * Counterpart to Solidity's `+` operator. - * - * Requirements: - * - * - Addition cannot overflow. - */ - function add(uint256 a, uint256 b) internal pure returns (uint256) { - uint256 c = a + b; - require(c >= a, "SafeMath: addition overflow"); - - return c; - } - - /** - * @dev Returns the subtraction of two unsigned integers, reverting on - * overflow (when the result is negative). - * - * Counterpart to Solidity's `-` operator. - * - * Requirements: - * - * - Subtraction cannot overflow. - */ - function sub(uint256 a, uint256 b) internal pure returns (uint256) { - return sub(a, b, "SafeMath: subtraction overflow"); - } - - /** - * @dev Returns the subtraction of two unsigned integers, reverting with custom message on - * overflow (when the result is negative). - * - * Counterpart to Solidity's `-` operator. - * - * Requirements: - * - * - Subtraction cannot overflow. - */ - function sub( - uint256 a, - uint256 b, - string memory errorMessage - ) internal pure returns (uint256) { - require(b <= a, errorMessage); - uint256 c = a - b; - - return c; - } - - /** - * @dev Returns the multiplication of two unsigned integers, reverting on - * overflow. - * - * Counterpart to Solidity's `*` operator. - * - * Requirements: - * - * - Multiplication cannot overflow. - */ - function mul(uint256 a, uint256 b) internal pure returns (uint256) { - // Gas optimization: this is cheaper than requiring 'a' not being zero, but the - // benefit is lost if 'b' is also tested. - // See: https://github.com/OpenZeppelin/openzeppelin-contracts/pull/522 - if (a == 0) { - return 0; - } - - uint256 c = a * b; - require(c / a == b, "SafeMath: multiplication overflow"); - - return c; - } - - /** - * @dev Returns the integer division of two unsigned integers. Reverts on - * division by zero. The result is rounded towards zero. - * - * Counterpart to Solidity's `/` operator. Note: this function uses a - * `revert` opcode (which leaves remaining gas untouched) while Solidity - * uses an invalid opcode to revert (consuming all remaining gas). - * - * Requirements: - * - * - The divisor cannot be zero. - */ - function div(uint256 a, uint256 b) internal pure returns (uint256) { - return div(a, b, "SafeMath: division by zero"); - } - - /** - * @dev Returns the integer division of two unsigned integers. Reverts with custom message on - * division by zero. The result is rounded towards zero. - * - * Counterpart to Solidity's `/` operator. Note: this function uses a - * `revert` opcode (which leaves remaining gas untouched) while Solidity - * uses an invalid opcode to revert (consuming all remaining gas). - * - * Requirements: - * - * - The divisor cannot be zero. - */ - function div( - uint256 a, - uint256 b, - string memory errorMessage - ) internal pure returns (uint256) { - require(b > 0, errorMessage); - uint256 c = a / b; - // assert(a == b * c + a % b); // There is no case in which this doesn't hold - - return c; - } - - /** - * @dev Returns the remainder of dividing two unsigned integers. (unsigned integer modulo), - * Reverts when dividing by zero. - * - * Counterpart to Solidity's `%` operator. This function uses a `revert` - * opcode (which leaves remaining gas untouched) while Solidity uses an - * invalid opcode to revert (consuming all remaining gas). - * - * Requirements: - * - * - The divisor cannot be zero. - */ - function mod(uint256 a, uint256 b) internal pure returns (uint256) { - return mod(a, b, "SafeMath: modulo by zero"); - } - - /** - * @dev Returns the remainder of dividing two unsigned integers. (unsigned integer modulo), - * Reverts with custom message when dividing by zero. - * - * Counterpart to Solidity's `%` operator. This function uses a `revert` - * opcode (which leaves remaining gas untouched) while Solidity uses an - * invalid opcode to revert (consuming all remaining gas). - * - * Requirements: - * - * - The divisor cannot be zero. - */ - function mod( - uint256 a, - uint256 b, - string memory errorMessage - ) internal pure returns (uint256) { - require(b != 0, errorMessage); - return a % b; - } - - // babylonian method (https://en.wikipedia.org/wiki/Methods_of_computing_square_roots#Babylonian_method) - function sqrrt(uint256 a) internal pure returns (uint256 c) { - if (a > 3) { - c = a; - uint256 b = add(div(a, 2), 1); - while (b < c) { - c = b; - b = div(add(div(a, b), b), 2); - } - } else if (a != 0) { - c = 1; - } - } - - /* - * Expects percentage to be trailed by 00, - */ - function percentageAmount(uint256 total_, uint8 percentage_) internal pure returns (uint256 percentAmount_) { - return div(mul(total_, percentage_), 1000); - } - - /* - * Expects percentage to be trailed by 00, - */ - function substractPercentage(uint256 total_, uint8 percentageToSub_) internal pure returns (uint256 result_) { - return sub(total_, div(mul(total_, percentageToSub_), 1000)); - } - - function percentageOfTotal(uint256 part_, uint256 total_) internal pure returns (uint256 percent_) { - return div(mul(part_, 100), total_); - } - - /** - * Taken from Hypersonic https://github.com/M2629/HyperSonic/blob/main/Math.sol - * @dev Returns the average of two numbers. The result is rounded towards - * zero. - */ - function average(uint256 a, uint256 b) internal pure returns (uint256) { - // (a + b) / 2 can overflow, so we distribute - return (a / 2) + (b / 2) + (((a % 2) + (b % 2)) / 2); - } - - function quadraticPricing(uint256 payment_, uint256 multiplier_) internal pure returns (uint256) { - return sqrrt(mul(multiplier_, payment_)); - } - - function bondingCurve(uint256 supply_, uint256 multiplier_) internal pure returns (uint256) { - return mul(multiplier_, supply_); - } -} - -// OpenZeppelin Contracts (last updated v4.7.0) (token/ERC20/utils/SafeERC20.sol) - - - - - -// OpenZeppelin Contracts v4.4.1 (token/ERC20/extensions/draft-IERC20Permit.sol) - - - -/** - * @dev Interface of the ERC20 Permit extension allowing approvals to be made via signatures, as defined in - * https://eips.ethereum.org/EIPS/eip-2612[EIP-2612]. - * - * Adds the {permit} method, which can be used to change an account's ERC20 allowance (see {IERC20-allowance}) by - * presenting a message signed by the account. By not relying on {IERC20-approve}, the token holder account doesn't - * need to send a transaction, and thus is not required to hold Ether at all. - */ -interface IERC20Permit { - /** - * @dev Sets `value` as the allowance of `spender` over ``owner``'s tokens, - * given ``owner``'s signed approval. - * - * IMPORTANT: The same issues {IERC20-approve} has related to transaction - * ordering also apply here. - * - * Emits an {Approval} event. - * - * Requirements: - * - * - `spender` cannot be the zero address. - * - `deadline` must be a timestamp in the future. - * - `v`, `r` and `s` must be a valid `secp256k1` signature from `owner` - * over the EIP712-formatted function arguments. - * - the signature must use ``owner``'s current nonce (see {nonces}). - * - * For more information on the signature format, see the - * https://eips.ethereum.org/EIPS/eip-2612#specification[relevant EIP - * section]. - */ - function permit( - address owner, - address spender, - uint256 value, - uint256 deadline, - uint8 v, - bytes32 r, - bytes32 s - ) external; - - /** - * @dev Returns the current nonce for `owner`. This value must be - * included whenever a signature is generated for {permit}. - * - * Every successful call to {permit} increases ``owner``'s nonce by one. This - * prevents a signature from being used multiple times. - */ - function nonces(address owner) external view returns (uint256); - - /** - * @dev Returns the domain separator used in the encoding of the signature for {permit}, as defined by {EIP712}. - */ - // solhint-disable-next-line func-name-mixedcase - function DOMAIN_SEPARATOR() external view returns (bytes32); -} - - - -/** - * @title SafeERC20 - * @dev Wrappers around ERC20 operations that throw on failure (when the token - * contract returns false). Tokens that return no value (and instead revert or - * throw on failure) are also supported, non-reverting calls are assumed to be - * successful. - * To use this library you can add a `using SafeERC20 for IERC20;` statement to your contract, - * which allows you to call the safe operations as `token.safeTransfer(...)`, etc. - */ -library SafeERC20 { - using Address for address; - - function safeTransfer( - IERC20 token, - address to, - uint256 value - ) internal { - _callOptionalReturn(token, abi.encodeWithSelector(token.transfer.selector, to, value)); - } - - function safeTransferFrom( - IERC20 token, - address from, - address to, - uint256 value - ) internal { - _callOptionalReturn(token, abi.encodeWithSelector(token.transferFrom.selector, from, to, value)); - } - - /** - * @dev Deprecated. This function has issues similar to the ones found in - * {IERC20-approve}, and its usage is discouraged. - * - * Whenever possible, use {safeIncreaseAllowance} and - * {safeDecreaseAllowance} instead. - */ - function safeApprove( - IERC20 token, - address spender, - uint256 value - ) internal { - // safeApprove should only be called when setting an initial allowance, - // or when resetting it to zero. To increase and decrease it, use - // 'safeIncreaseAllowance' and 'safeDecreaseAllowance' - require( - (value == 0) || (token.allowance(address(this), spender) == 0), - "SafeERC20: approve from non-zero to non-zero allowance" - ); - _callOptionalReturn(token, abi.encodeWithSelector(token.approve.selector, spender, value)); - } - - function safeIncreaseAllowance( - IERC20 token, - address spender, - uint256 value - ) internal { - uint256 newAllowance = token.allowance(address(this), spender) + value; - _callOptionalReturn(token, abi.encodeWithSelector(token.approve.selector, spender, newAllowance)); - } - - function safeDecreaseAllowance( - IERC20 token, - address spender, - uint256 value - ) internal { - unchecked { - uint256 oldAllowance = token.allowance(address(this), spender); - require(oldAllowance >= value, "SafeERC20: decreased allowance below zero"); - uint256 newAllowance = oldAllowance - value; - _callOptionalReturn(token, abi.encodeWithSelector(token.approve.selector, spender, newAllowance)); - } - } - - function safePermit( - IERC20Permit token, - address owner, - address spender, - uint256 value, - uint256 deadline, - uint8 v, - bytes32 r, - bytes32 s - ) internal { - uint256 nonceBefore = token.nonces(owner); - token.permit(owner, spender, value, deadline, v, r, s); - uint256 nonceAfter = token.nonces(owner); - require(nonceAfter == nonceBefore + 1, "SafeERC20: permit did not succeed"); - } - - /** - * @dev Imitates a Solidity high-level call (i.e. a regular function call to a contract), relaxing the requirement - * on the return value: the return value is optional (but if data is returned, it must not be false). - * @param token The token targeted by the call. - * @param data The call data (encoded using abi.encode or one of its variants). - */ - function _callOptionalReturn(IERC20 token, bytes memory data) private { - // We need to perform a low level call here, to bypass Solidity's return data size checking mechanism, since - // we're implementing it ourselves. We use {Address.functionCall} to perform this call, which verifies that - // the target address contains contract code and also asserts for success in the low-level call. - - bytes memory returndata = address(token).functionCall(data, "SafeERC20: low-level call failed"); - if (returndata.length > 0) { - // Return data is optional - require(abi.decode(returndata, (bool)), "SafeERC20: ERC20 operation did not succeed"); - } - } -} - - - - - - - - - - - - - - -/** - * @dev Provides information about the current execution context, including the - * sender of the transaction and its data. While these are generally available - * via msg.sender and msg.data, they should not be accessed in such a direct - * manner, since when dealing with meta-transactions the account sending and - * paying for execution may not be the actual sender (as far as an application - * is concerned). - * - * This contract is only required for intermediate, library-like contracts. - */ -abstract contract Context { - function _msgSender() internal view virtual returns (address) { - return msg.sender; - } - - function _msgData() internal view virtual returns (bytes calldata) { - return msg.data; - } -} - - -/** - * @dev Contract module which provides a basic access control mechanism, where - * there is an account (an owner) that can be granted exclusive access to - * specific functions. - * - * By default, the owner account will be the one that deploys the contract. This - * can later be changed with {transferOwnership}. - * - * This module is used through inheritance. It will make available the modifier - * `onlyOwner`, which can be applied to your functions to restrict their use to - * the owner. - */ -abstract contract Ownable is Context { - address private _owner; - - event OwnershipTransferred(address indexed previousOwner, address indexed newOwner); - - /** - * @dev Initializes the contract setting the deployer as the initial owner. - */ - constructor() { - _transferOwnership(_msgSender()); - } - - /** - * @dev Throws if called by any account other than the owner. - */ - modifier onlyOwner() { - _checkOwner(); - _; - } - - /** - * @dev Returns the address of the current owner. - */ - function owner() public view virtual returns (address) { - return _owner; - } - - /** - * @dev Throws if the sender is not the owner. - */ - function _checkOwner() internal view virtual { - require(owner() == _msgSender(), "Ownable: caller is not the owner"); - } - - /** - * @dev Leaves the contract without owner. It will not be possible to call - * `onlyOwner` functions anymore. Can only be called by the current owner. - * - * NOTE: Renouncing ownership will leave the contract without an owner, - * thereby removing any functionality that is only available to the owner. - */ - function renounceOwnership() public virtual onlyOwner { - _transferOwnership(address(0)); - } - - /** - * @dev Transfers ownership of the contract to a new account (`newOwner`). - * Can only be called by the current owner. - */ - function transferOwnership(address newOwner) public virtual onlyOwner { - require(newOwner != address(0), "Ownable: new owner is the zero address"); - _transferOwnership(newOwner); - } - - /** - * @dev Transfers ownership of the contract to a new account (`newOwner`). - * Internal function without access restriction. - */ - function _transferOwnership(address newOwner) internal virtual { - address oldOwner = _owner; - _owner = newOwner; - emit OwnershipTransferred(oldOwner, newOwner); - } -} - - -contract Operator is Ownable { - address public operator; - uint256 constant baseRate = 10000; - - modifier onlyOperator { - require(msg.sender == owner() || msg.sender == operator, "no permission"); - _; - } - - function setOperator(address operator_) external onlyOwner { - operator = operator_; - } - - - function getCurrTime() external view returns(uint256) { - return block.timestamp; - } - - function getBlockNum() external view returns(uint256) { - return block.number; - } - -} - - - - - -/** - * @dev Library for managing - * https://en.wikipedia.org/wiki/Set_(abstract_data_type)[sets] of primitive - * types. - * - * Sets have the following properties: - * - * - Elements are added, removed, and checked for existence in constant time - * (O(1)). - * - Elements are enumerated in O(n). No guarantees are made on the ordering. - * - * ``` - * contract Example { - * // Add the library methods - * using EnumerableSet for EnumerableSet.AddressSet; - * - * // Declare a set state variable - * EnumerableSet.AddressSet private mySet; - * } - * ``` - * - * As of v3.3.0, sets of type `bytes32` (`Bytes32Set`), `address` (`AddressSet`) - * and `uint256` (`UintSet`) are supported. - * - * [WARNING] - * ==== - * Trying to delete such a structure from storage will likely result in data corruption, rendering the structure unusable. - * See https://github.com/ethereum/solidity/pull/11843[ethereum/solidity#11843] for more info. - * - * In order to clean an EnumerableSet, you can either remove all elements one by one or create a fresh instance using an array of EnumerableSet. - * ==== - */ - -library EnumerableSet { - // To implement this library for multiple types with as little code - // repetition as possible, we write it in terms of a generic Set type with - // bytes32 values. - // The Set implementation uses private functions, and user-facing - // implementations (such as AddressSet) are just wrappers around the - // underlying Set. - // This means that we can only create new EnumerableSets for types that fit - // in bytes32. - - struct Set { - // Storage of set values - bytes32[] _values; - // Position of the value in the `values` array, plus 1 because index 0 - // means a value is not in the set. - mapping(bytes32 => uint256) _indexes; - } - - /** - * @dev Add a value to a set. O(1). - * - * Returns true if the value was added to the set, that is if it was not - * already present. - */ - function _add(Set storage set, bytes32 value) private returns (bool) { - if (!_contains(set, value)) { - set._values.push(value); - // The value is stored at length-1, but we add 1 to all indexes - // and use 0 as a sentinel value - set._indexes[value] = set._values.length; - return true; - } else { - return false; - } - } - - /** - * @dev Removes a value from a set. O(1). - * - * Returns true if the value was removed from the set, that is if it was - * present. - */ - function _remove(Set storage set, bytes32 value) private returns (bool) { - // We read and store the value's index to prevent multiple reads from the same storage slot - uint256 valueIndex = set._indexes[value]; - - if (valueIndex != 0) { - // Equivalent to contains(set, value) - // To delete an element from the _values array in O(1), we swap the element to delete with the last one in - // the array, and then remove the last element (sometimes called as 'swap and pop'). - // This modifies the order of the array, as noted in {at}. - - uint256 toDeleteIndex = valueIndex - 1; - uint256 lastIndex = set._values.length - 1; - - if (lastIndex != toDeleteIndex) { - bytes32 lastValue = set._values[lastIndex]; - - // Move the last value to the index where the value to delete is - set._values[toDeleteIndex] = lastValue; - // Update the index for the moved value - set._indexes[lastValue] = valueIndex; // Replace lastValue's index to valueIndex - } - - // Delete the slot where the moved value was stored - set._values.pop(); - - // Delete the index for the deleted slot - delete set._indexes[value]; - - return true; - } else { - return false; - } - } - - /** - * @dev Returns true if the value is in the set. O(1). - */ - function _contains(Set storage set, bytes32 value) private view returns (bool) { - return set._indexes[value] != 0; - } - - /** - * @dev Returns the number of values on the set. O(1). - */ - function _length(Set storage set) private view returns (uint256) { - return set._values.length; - } - - /** - * @dev Returns the value stored at position `index` in the set. O(1). - * - * Note that there are no guarantees on the ordering of values inside the - * array, and it may change when more values are added or removed. - * - * Requirements: - * - * - `index` must be strictly less than {length}. - */ - function _at(Set storage set, uint256 index) private view returns (bytes32) { - return set._values[index]; - } - - /** - * @dev Return the entire set in an array - * - * WARNING: This operation will copy the entire storage to memory, which can be quite expensive. This is designed - * to mostly be used by view accessors that are queried without any gas fees. Developers should keep in mind that - * this function has an unbounded cost, and using it as part of a state-changing function may render the function - * uncallable if the set grows to a point where copying to memory consumes too much gas to fit in a block. - */ - function _values(Set storage set) private view returns (bytes32[] memory) { - return set._values; - } - - // Bytes32Set - - struct Bytes32Set { - Set _inner; - } - - /** - * @dev Add a value to a set. O(1). - * - * Returns true if the value was added to the set, that is if it was not - * already present. - */ - function add(Bytes32Set storage set, bytes32 value) internal returns (bool) { - return _add(set._inner, value); - } - - /** - * @dev Removes a value from a set. O(1). - * - * Returns true if the value was removed from the set, that is if it was - * present. - */ - function remove(Bytes32Set storage set, bytes32 value) internal returns (bool) { - return _remove(set._inner, value); - } - - /** - * @dev Returns true if the value is in the set. O(1). - */ - function contains(Bytes32Set storage set, bytes32 value) internal view returns (bool) { - return _contains(set._inner, value); - } - - /** - * @dev Returns the number of values in the set. O(1). - */ - function length(Bytes32Set storage set) internal view returns (uint256) { - return _length(set._inner); - } - - /** - * @dev Returns the value stored at position `index` in the set. O(1). - * - * Note that there are no guarantees on the ordering of values inside the - * array, and it may change when more values are added or removed. - * - * Requirements: - * - * - `index` must be strictly less than {length}. - */ - function at(Bytes32Set storage set, uint256 index) internal view returns (bytes32) { - return _at(set._inner, index); - } - - /** - * @dev Return the entire set in an array - * - * WARNING: This operation will copy the entire storage to memory, which can be quite expensive. This is designed - * to mostly be used by view accessors that are queried without any gas fees. Developers should keep in mind that - * this function has an unbounded cost, and using it as part of a state-changing function may render the function - * uncallable if the set grows to a point where copying to memory consumes too much gas to fit in a block. - */ - function values(Bytes32Set storage set) internal view returns (bytes32[] memory) { - return _values(set._inner); - } - - // AddressSet - - struct AddressSet { - Set _inner; - } - - /** - * @dev Add a value to a set. O(1). - * - * Returns true if the value was added to the set, that is if it was not - * already present. - */ - function add(AddressSet storage set, address value) internal returns (bool) { - return _add(set._inner, bytes32(uint256(uint160(value)))); - } - - /** - * @dev Removes a value from a set. O(1). - * - * Returns true if the value was removed from the set, that is if it was - * present. - */ - function remove(AddressSet storage set, address value) internal returns (bool) { - return _remove(set._inner, bytes32(uint256(uint160(value)))); - } - - /** - * @dev Returns true if the value is in the set. O(1). - */ - function contains(AddressSet storage set, address value) internal view returns (bool) { - return _contains(set._inner, bytes32(uint256(uint160(value)))); - } - - /** - * @dev Returns the number of values in the set. O(1). - */ - function length(AddressSet storage set) internal view returns (uint256) { - return _length(set._inner); - } - - /** - * @dev Returns the value stored at position `index` in the set. O(1). - * - * Note that there are no guarantees on the ordering of values inside the - * array, and it may change when more values are added or removed. - * - * Requirements: - * - * - `index` must be strictly less than {length}. - */ - function at(AddressSet storage set, uint256 index) internal view returns (address) { - return address(uint160(uint256(_at(set._inner, index)))); - } - - /** - * @dev Return the entire set in an array - * - * WARNING: This operation will copy the entire storage to memory, which can be quite expensive. This is designed - * to mostly be used by view accessors that are queried without any gas fees. Developers should keep in mind that - * this function has an unbounded cost, and using it as part of a state-changing function may render the function - * uncallable if the set grows to a point where copying to memory consumes too much gas to fit in a block. - */ - function values(AddressSet storage set) internal view returns (address[] memory) { - bytes32[] memory store = _values(set._inner); - address[] memory result; - - /// @solidity memory-safe-assembly - assembly { - result := store - } - - return result; - } - - // UintSet - - struct UintSet { - Set _inner; - } - - /** - * @dev Add a value to a set. O(1). - * - * Returns true if the value was added to the set, that is if it was not - * already present. - */ - function add(UintSet storage set, uint256 value) internal returns (bool) { - return _add(set._inner, bytes32(value)); - } - - /** - * @dev Removes a value from a set. O(1). - * - * Returns true if the value was removed from the set, that is if it was - * present. - */ - function remove(UintSet storage set, uint256 value) internal returns (bool) { - return _remove(set._inner, bytes32(value)); - } - - /** - * @dev Returns true if the value is in the set. O(1). - */ - function contains(UintSet storage set, uint256 value) internal view returns (bool) { - return _contains(set._inner, bytes32(value)); - } - - /** - * @dev Returns the number of values on the set. O(1). - */ - function length(UintSet storage set) internal view returns (uint256) { - return _length(set._inner); - } - - /** - * @dev Returns the value stored at position `index` in the set. O(1). - * - * Note that there are no guarantees on the ordering of values inside the - * array, and it may change when more values are added or removed. - * - * Requirements: - * - * - `index` must be strictly less than {length}. - */ - function at(UintSet storage set, uint256 index) internal view returns (uint256) { - return uint256(_at(set._inner, index)); - } - - /** - * @dev Return the entire set in an array - * - * WARNING: This operation will copy the entire storage to memory, which can be quite expensive. This is designed - * to mostly be used by view accessors that are queried without any gas fees. Developers should keep in mind that - * this function has an unbounded cost, and using it as part of a state-changing function may render the function - * uncallable if the set grows to a point where copying to memory consumes too much gas to fit in a block. - */ - function values(UintSet storage set) internal view returns (uint256[] memory) { - bytes32[] memory store = _values(set._inner); - uint256[] memory result; - - /// @solidity memory-safe-assembly - assembly { - result := store - } - - return result; - } -} - - -contract ActivityPool is Operator { - using SafeMath for uint256; - using SafeERC20 for IERC20; - using EnumerableSet for EnumerableSet.AddressSet; - using EnumerableSet for EnumerableSet.UintSet; - - event AddNewAct(uint256 id); - event Bet(address user, uint256 pID, uint256 bType, uint256 amount, uint256 time); - event SetPrize(uint256 pID, uint256 bType); - event Claim(address user, uint256 pID, uint256 bType, uint256 amount); - event RemovePeriodAct(uint256 pID); - - uint256 public constant muti = 1e18; - uint256 public periodID; - uint256 public betID; - - struct UserInfo { - address user; - uint256 pID; - uint256 amount; - uint256 betTime; - uint256 bType; - uint256 claimAmount; - } - - struct ActInfo { - string name; - string aName; - string bName; - address rewardToken; - uint256 startTime; - uint256 endTime; - uint256 minAmount; - uint256 maxAmount; - uint256 aAmount; - uint256 bAmount; - uint256 winType; - bool isBet; - } - - struct TimeInfo { - uint256 time; - uint256 aAmount; - uint256 bAmount; - } - - struct BestInfo { - address aUser; - address bUser; - uint256 aBet; - uint256 bBet; - } - - mapping(uint256 => BestInfo) bestInfo; - mapping(uint256 => uint256) public timeID; - mapping(uint256 => mapping(uint256 => TimeInfo)) public timeInfo; - mapping(address => mapping(uint256 => uint256)) public userBet; - mapping(uint256 => UserInfo) public betInfo; - mapping(uint256 => uint256) public perAmount; - mapping(uint256 => ActInfo) public actInfo; - mapping(uint256 => mapping(uint256 => string)) public descripName; - - mapping(address => EnumerableSet.UintSet) userPid; - mapping(uint256 => EnumerableSet.AddressSet) aUsers; - mapping(uint256 => EnumerableSet.AddressSet) bUsers; - EnumerableSet.UintSet activePeriod; - EnumerableSet.UintSet removePeriod; - - function addNewAct( - string memory name, - string memory aName, - string memory bName, - address token, - uint256 startTime, - uint256 endTime, - uint256 minAmount, - uint256 maxAmount - ) external onlyOperator { - - checkAdd(msg.sender, startTime, endTime, minAmount, maxAmount); - uint256 id = ++periodID; - actInfo[id].name = name; - actInfo[id].aName = aName; - actInfo[id].bName = bName; - actInfo[id].startTime = startTime; - actInfo[id].endTime = endTime; - actInfo[id].minAmount = minAmount; - actInfo[id].maxAmount = maxAmount; - actInfo[id].rewardToken = token; - descripName[id][1] = aName; - descripName[id][2] = bName; - activePeriod.add(id); - - emit AddNewAct(id); - } - - - function removePeriodAct(uint256 pID) external onlyOperator { - checkRemove(pID); - - activePeriod.remove(pID); - removePeriod.add(pID); - - emit RemovePeriodAct(pID); - } - - - function bet(uint256 pID, uint256 bType, uint256 amount) external payable { - checkBet(msg.sender, pID, bType, amount); - if(actInfo[pID].rewardToken == address(0)) { - require(msg.value == amount, "value err"); - } else { - require(msg.value == 0, "value amount err"); - } - - if(bType == 1) { - if(amount > bestInfo[pID].aBet) { - bestInfo[pID].aUser = msg.sender; - bestInfo[pID].aBet = amount; - } - } else { - if(amount > bestInfo[pID].bBet) { - bestInfo[pID].bUser = msg.sender; - bestInfo[pID].bBet = amount; - } - } - - userPid[msg.sender].add(pID); - uint256 id = ++betID; - userBet[msg.sender][pID] = id; - - if(bType == 1) { - aUsers[pID].add(msg.sender); - actInfo[pID].aAmount = actInfo[pID].aAmount.add(amount); - } else { - bUsers[pID].add(msg.sender); - actInfo[pID].bAmount = actInfo[pID].bAmount.add(amount); - } - - actInfo[pID].isBet = true; - betInfo[id].user = msg.sender; - betInfo[id].pID = pID; - betInfo[id].amount = amount; - betInfo[id].betTime = block.timestamp; - betInfo[id].bType = bType; - - uint256 tID = ++timeID[pID]; - timeInfo[pID][tID].time = block.timestamp; - timeInfo[pID][tID].aAmount = actInfo[pID].aAmount; - timeInfo[pID][tID].bAmount = actInfo[pID].bAmount; - - if(actInfo[pID].rewardToken != address(0)) { - IERC20(actInfo[pID].rewardToken).safeTransferFrom(msg.sender, address(this), amount); - } - emit Bet(msg.sender, pID, bType, amount, betInfo[id].betTime); - } - - function setPrize(uint256 pID, uint256 bType) external onlyOperator { - checkSetPrize(msg.sender, pID, bType); - - if(block.timestamp <= actInfo[pID].startTime) { - actInfo[pID].startTime = block.timestamp; - - } - actInfo[pID].endTime = block.timestamp; - - actInfo[pID].winType = bType; - perAmount[pID] = getPerAmount(pID, bType); - - emit SetPrize(pID, bType); - } - - function recive() public payable {} - - function claim(uint256 pID) external { - uint256 amount = checkClaim(msg.sender, pID); - - uint256 id = userBet[msg.sender][pID]; - betInfo[id].claimAmount = amount; - if(actInfo[pID].rewardToken != address(0)) { - IERC20(actInfo[pID].rewardToken).safeTransfer(msg.sender, amount); - } else { - payable(msg.sender).transfer(amount); - } - - emit Claim(msg.sender, pID, betInfo[id].bType, amount); - } - - function checkClaim(address user, uint256 pID) public view returns(uint256 amount) { - require(userPid[user].contains(pID), "not bet"); - uint256 id = userBet[user][pID]; - require(betInfo[id].user == user, "not user"); - require(actInfo[pID].winType != 0, "not prize"); - require(betInfo[id].claimAmount == 0, "has claim"); - - if(actInfo[pID].winType != 3) { - require(actInfo[pID].winType == betInfo[id].bType, "not right"); - amount = perAmount[pID].mul(betInfo[id].amount).div(muti); - require(amount > 0, "no amount"); - } else { - amount = betInfo[id].amount; - } - - return amount; - } - - function getActualRate( - address user, - uint256 pID, - uint256 bType, - uint256 amount - ) external view returns(uint256, uint256, bool) { - if(bType < 1 || bType > 2 || !activePeriod.contains(pID)) { - return (0, 0, false); - } else if(userBet[user][pID] != 0 || actInfo[pID].winType != 0 || amount == 0) { - (uint256 ra, uint256 rb) = getRate(pID, timeID[pID]); - return (ra, rb, false); - } else { - (uint256 aAmount, uint256 bAmount) = (actInfo[pID].aAmount, actInfo[pID].bAmount); - if(bType == 1) { - aAmount = aAmount.add(amount); - } else { - bAmount = bAmount.add(amount); - } - - uint256 total = aAmount.add(bAmount); - if(bAmount == 0 && aAmount != 0) { - return (muti, 0, true); - } - if(bAmount != 0 && aAmount == 0) { - return (0, muti, true); - } - return (total.mul(muti).div(aAmount), total.mul(muti).div(bAmount), true); - } - } - - function getRate(uint256 pID, uint256 tID) public view returns(uint256, uint256) { - (uint256 aAmount, uint256 bAmount) = (timeInfo[pID][tID].aAmount, timeInfo[pID][tID].bAmount); - uint256 total = aAmount.add(bAmount); - if(total == 0) { - return (0, 0); - } - if(bAmount == 0 && aAmount != 0) { - return (muti, 0); - } - if(bAmount != 0 && aAmount == 0) { - return (0, muti); - } - return (total.mul(muti).div(aAmount), total.mul(muti).div(bAmount)); - } - - function getBestInfo(uint256 pID) - external - view - returns(address aUser, address bUser, uint256 aBet, uint256 bBet, uint256 aReward, uint256 bReward) - { - aUser = bestInfo[pID].aUser; - bUser = bestInfo[pID].bUser; - aBet = bestInfo[pID].aBet; - bBet = bestInfo[pID].bBet; - aReward = getPerAmount(pID, 1).mul(aBet).div(muti); - bReward = getPerAmount(pID, 2).mul(bBet).div(muti); - } - - function getPerAmount(uint256 pID, uint256 bType) public view returns(uint256) { - uint256 total = actInfo[pID].aAmount.add(actInfo[pID].bAmount); - if(total == 0) { - return 0; - } - - if(actInfo[pID].winType == 3) { - return muti; - } - - if(bType == 1) { - if(actInfo[pID].aAmount == 0 || actInfo[pID].winType == 2) { - return 0; - } - return total.mul(muti).div(actInfo[pID].aAmount); - } - - if(bType == 2) { - if(actInfo[pID].bAmount == 0 || actInfo[pID].winType == 1) { - return 0; - } - return total.mul(muti).div(actInfo[pID].bAmount); - } - - return 0; - - } - - function checkSetPrize(address user, uint256 pID, uint256 bType) public view returns(bool) { - require(user == owner() || user == operator, "no permission"); - require(bType > 0 && bType <= 3, "type err"); - require(activePeriod.contains(pID), "not active"); - require(actInfo[pID].winType == 0, "has set"); - - return true; - } - - function checkBet( - address user, - uint256 pID, - uint256 bType, - uint256 amount - ) public view returns(bool) { - require(activePeriod.contains(pID), "not active"); - require(actInfo[pID].startTime <= block.timestamp, "not start"); - require(actInfo[pID].endTime > block.timestamp, "has end"); - require(!userPid[user].contains(pID), "has bet"); - require(bType > 0 && bType < 3, "type err"); - require(amount >= actInfo[pID].minAmount && amount <= actInfo[pID].maxAmount, "amount err"); - if(actInfo[pID].rewardToken != address(0)) { - require(IERC20(actInfo[pID].rewardToken).allowance(user, address(this)) >= amount, "not approve enough"); - require(IERC20(actInfo[pID].rewardToken).balanceOf(user) >= amount, "not enough"); - } else { - require(user.balance >= amount, "main token err"); - } - - return true; - } - - - function checkRemove(uint256 pID) public view returns(bool) { - require(activePeriod.contains(pID), "not in"); - require(!actInfo[pID].isBet, "has bet"); - - return true; - } - - function checkAdd( - address user, - uint256 startTime, - uint256 endTime, - uint256 minAmount, - uint256 maxAmount - ) public view returns(bool) { - require(user == owner() || user == operator, "no permission"); - require(startTime > block.timestamp, "startTime err"); - require(endTime > startTime, "endTime err"); - require(minAmount > 0 && maxAmount > minAmount, "amount err"); - - return true; - } - - function getStatus(uint256 pID) external view returns(uint256) { - if(!removePeriod.contains(pID) && !activePeriod.contains(pID)) { - return 5; - } else if(removePeriod.contains(pID)) { - return 6; - } else if(block.timestamp < actInfo[pID].startTime) { - return 1; - } else if ( - actInfo[pID].startTime <= block.timestamp && - actInfo[pID].endTime > block.timestamp - ) { - return 2; - } else if (actInfo[pID].endTime <= block.timestamp && actInfo[pID].winType == 0){ - return 3; - } else if(actInfo[pID].winType != 0) { - return 4; - } - return 0; - } - - function getUserPidNum(address user) external view returns(uint256) { - return userPid[user].length(); - } - - function getUserPid(address user, uint256 index) external view returns(uint256) { - return userPid[user].at(index); - } - - function getAUsersNum(uint256 pID) external view returns(uint256) { - return aUsers[pID].length(); - } - - function getAUsers(uint256 pID, uint256 index) external view returns(address) { - return aUsers[pID].at(index); - } - - function getBUsersNum(uint256 pID) external view returns(uint256) { - return bUsers[pID].length(); - } - - function getBUsers(uint256 pID, uint256 index) external view returns(address) { - return bUsers[pID].at(index); - } - - function getActivePeriodNum() external view returns(uint256) { - return activePeriod.length(); - } - - function getActivePeriod(uint256 index) external view returns(uint256) { - return activePeriod.at(index); - } - - function getRemovePeriodNum() external view returns(uint256) { - return removePeriod.length(); - } - - function getRemovePeriod(uint256 index) external view returns(uint256) { - return removePeriod.at(index); - } -} \ No newline at end of file diff --git a/app/api/uploads/ActivityPool-1729789209485-72963277.sol b/app/api/uploads/ActivityPool-1729789209485-72963277.sol deleted file mode 100644 index daf3372..0000000 --- a/app/api/uploads/ActivityPool-1729789209485-72963277.sol +++ /dev/null @@ -1,1648 +0,0 @@ -// SPDX-License-Identifier: MIT -// OpenZeppelin Contracts (last updated v4.7.0) (utils/Address.sol) - -pragma solidity ^0.8.1; - -/** - * @dev Collection of functions related to the address type - */ -library Address { - /** - * @dev Returns true if `account` is a contract. - * - * [IMPORTANT] - * ==== - * It is unsafe to assume that an address for which this function returns - * false is an externally-owned account (EOA) and not a contract. - * - * Among others, `isContract` will return false for the following - * types of addresses: - * - * - an externally-owned account - * - a contract in construction - * - an address where a contract will be created - * - an address where a contract lived, but was destroyed - * ==== - * - * [IMPORTANT] - * ==== - * You shouldn't rely on `isContract` to protect against flash loan attacks! - * - * Preventing calls from contracts is highly discouraged. It breaks composability, breaks support for smart wallets - * like Gnosis Safe, and does not provide security since it can be circumvented by calling from a contract - * constructor. - * ==== - */ - function isContract(address account) internal view returns (bool) { - // This method relies on extcodesize/address.code.length, which returns 0 - // for contracts in construction, since the code is only stored at the end - // of the constructor execution. - - return account.code.length > 0; - } - - /** - * @dev Replacement for Solidity's `transfer`: sends `amount` wei to - * `recipient`, forwarding all available gas and reverting on errors. - * - * https://eips.ethereum.org/EIPS/eip-1884[EIP1884] increases the gas cost - * of certain opcodes, possibly making contracts go over the 2300 gas limit - * imposed by `transfer`, making them unable to receive funds via - * `transfer`. {sendValue} removes this limitation. - * - * https://diligence.consensys.net/posts/2019/09/stop-using-soliditys-transfer-now/[Learn more]. - * - * IMPORTANT: because control is transferred to `recipient`, care must be - * taken to not create reentrancy vulnerabilities. Consider using - * {ReentrancyGuard} or the - * https://solidity.readthedocs.io/en/v0.5.11/security-considerations.html#use-the-checks-effects-interactions-pattern[checks-effects-interactions pattern]. - */ - function sendValue(address payable recipient, uint256 amount) internal { - require(address(this).balance >= amount, "Address: insufficient balance"); - - (bool success, ) = recipient.call{value: amount}(""); - require(success, "Address: unable to send value, recipient may have reverted"); - } - - /** - * @dev Performs a Solidity function call using a low level `call`. A - * plain `call` is an unsafe replacement for a function call: use this - * function instead. - * - * If `target` reverts with a revert reason, it is bubbled up by this - * function (like regular Solidity function calls). - * - * Returns the raw returned data. To convert to the expected return value, - * use https://solidity.readthedocs.io/en/latest/units-and-global-variables.html?highlight=abi.decode#abi-encoding-and-decoding-functions[`abi.decode`]. - * - * Requirements: - * - * - `target` must be a contract. - * - calling `target` with `data` must not revert. - * - * _Available since v3.1._ - */ - function functionCall(address target, bytes memory data) internal returns (bytes memory) { - return functionCallWithValue(target, data, 0, "Address: low-level call failed"); - } - - /** - * @dev Same as {xref-Address-functionCall-address-bytes-}[`functionCall`], but with - * `errorMessage` as a fallback revert reason when `target` reverts. - * - * _Available since v3.1._ - */ - function functionCall( - address target, - bytes memory data, - string memory errorMessage - ) internal returns (bytes memory) { - return functionCallWithValue(target, data, 0, errorMessage); - } - - /** - * @dev Same as {xref-Address-functionCall-address-bytes-}[`functionCall`], - * but also transferring `value` wei to `target`. - * - * Requirements: - * - * - the calling contract must have an ETH balance of at least `value`. - * - the called Solidity function must be `payable`. - * - * _Available since v3.1._ - */ - function functionCallWithValue( - address target, - bytes memory data, - uint256 value - ) internal returns (bytes memory) { - return functionCallWithValue(target, data, value, "Address: low-level call with value failed"); - } - - /** - * @dev Same as {xref-Address-functionCallWithValue-address-bytes-uint256-}[`functionCallWithValue`], but - * with `errorMessage` as a fallback revert reason when `target` reverts. - * - * _Available since v3.1._ - */ - function functionCallWithValue( - address target, - bytes memory data, - uint256 value, - string memory errorMessage - ) internal returns (bytes memory) { - require(address(this).balance >= value, "Address: insufficient balance for call"); - (bool success, bytes memory returndata) = target.call{value: value}(data); - return verifyCallResultFromTarget(target, success, returndata, errorMessage); - } - - /** - * @dev Same as {xref-Address-functionCall-address-bytes-}[`functionCall`], - * but performing a static call. - * - * _Available since v3.3._ - */ - function functionStaticCall(address target, bytes memory data) internal view returns (bytes memory) { - return functionStaticCall(target, data, "Address: low-level static call failed"); - } - - /** - * @dev Same as {xref-Address-functionCall-address-bytes-string-}[`functionCall`], - * but performing a static call. - * - * _Available since v3.3._ - */ - function functionStaticCall( - address target, - bytes memory data, - string memory errorMessage - ) internal view returns (bytes memory) { - (bool success, bytes memory returndata) = target.staticcall(data); - return verifyCallResultFromTarget(target, success, returndata, errorMessage); - } - - /** - * @dev Same as {xref-Address-functionCall-address-bytes-}[`functionCall`], - * but performing a delegate call. - * - * _Available since v3.4._ - */ - function functionDelegateCall(address target, bytes memory data) internal returns (bytes memory) { - return functionDelegateCall(target, data, "Address: low-level delegate call failed"); - } - - /** - * @dev Same as {xref-Address-functionCall-address-bytes-string-}[`functionCall`], - * but performing a delegate call. - * - * _Available since v3.4._ - */ - function functionDelegateCall( - address target, - bytes memory data, - string memory errorMessage - ) internal returns (bytes memory) { - (bool success, bytes memory returndata) = target.delegatecall(data); - return verifyCallResultFromTarget(target, success, returndata, errorMessage); - } - - /** - * @dev Tool to verify that a low level call to smart-contract was successful, and revert (either by bubbling - * the revert reason or using the provided one) in case of unsuccessful call or if target was not a contract. - * - * _Available since v4.8._ - */ - function verifyCallResultFromTarget( - address target, - bool success, - bytes memory returndata, - string memory errorMessage - ) internal view returns (bytes memory) { - if (success) { - if (returndata.length == 0) { - // only check isContract if the call was successful and the return data is empty - // otherwise we already know that it was a contract - require(isContract(target), "Address: call to non-contract"); - } - return returndata; - } else { - _revert(returndata, errorMessage); - } - } - - /** - * @dev Tool to verify that a low level call was successful, and revert if it wasn't, either by bubbling the - * revert reason or using the provided one. - * - * _Available since v4.3._ - */ - function verifyCallResult( - bool success, - bytes memory returndata, - string memory errorMessage - ) internal pure returns (bytes memory) { - if (success) { - return returndata; - } else { - _revert(returndata, errorMessage); - } - } - - function _revert(bytes memory returndata, string memory errorMessage) private pure { - // Look for revert reason and bubble it up if present - if (returndata.length > 0) { - // The easiest way to bubble the revert reason is using memory via assembly - /// @solidity memory-safe-assembly - assembly { - let returndata_size := mload(returndata) - revert(add(32, returndata), returndata_size) - } - } else { - revert(errorMessage); - } - } -} - -// OpenZeppelin Contracts (last updated v4.6.0) (token/ERC20/IERC20.sol) - - - -/** - * @dev Interface of the ERC20 standard as defined in the EIP. - */ -interface IERC20 { - /** - * @dev Emitted when `value` tokens are moved from one account (`from`) to - * another (`to`). - * - * Note that `value` may be zero. - */ - event Transfer(address indexed from, address indexed to, uint256 value); - - /** - * @dev Emitted when the allowance of a `spender` for an `owner` is set by - * a call to {approve}. `value` is the new allowance. - */ - event Approval(address indexed owner, address indexed spender, uint256 value); - - /** - * @dev Returns the amount of tokens in existence. - */ - function totalSupply() external view returns (uint256); - - /** - * @dev Returns the amount of tokens owned by `account`. - */ - function balanceOf(address account) external view returns (uint256); - - /** - * @dev Moves `amount` tokens from the caller's account to `to`. - * - * Returns a boolean value indicating whether the operation succeeded. - * - * Emits a {Transfer} event. - */ - function transfer(address to, uint256 amount) external returns (bool); - - /** - * @dev Returns the remaining number of tokens that `spender` will be - * allowed to spend on behalf of `owner` through {transferFrom}. This is - * zero by default. - * - * This value changes when {approve} or {transferFrom} are called. - */ - function allowance(address owner, address spender) external view returns (uint256); - - /** - * @dev Sets `amount` as the allowance of `spender` over the caller's tokens. - * - * Returns a boolean value indicating whether the operation succeeded. - * - * IMPORTANT: Beware that changing an allowance with this method brings the risk - * that someone may use both the old and the new allowance by unfortunate - * transaction ordering. One possible solution to mitigate this race - * condition is to first reduce the spender's allowance to 0 and set the - * desired value afterwards: - * https://github.com/ethereum/EIPs/issues/20#issuecomment-263524729 - * - * Emits an {Approval} event. - */ - function approve(address spender, uint256 amount) external returns (bool); - - /** - * @dev Moves `amount` tokens from `from` to `to` using the - * allowance mechanism. `amount` is then deducted from the caller's - * allowance. - * - * Returns a boolean value indicating whether the operation succeeded. - * - * Emits a {Transfer} event. - */ - function transferFrom( - address from, - address to, - uint256 amount - ) external returns (bool); - - - function mint(address account_, uint256 amount_) external; - - function burn(uint256 amount) external; - -} - - - - - - - - - - - -/** - * @dev Wrappers over Solidity's arithmetic operations with added overflow - * checks. - * - * Arithmetic operations in Solidity wrap on overflow. This can easily result - * in bugs, because programmers usually assume that an overflow raises an - * error, which is the standard behavior in high level programming languages. - * `SafeMath` restores this intuition by reverting the transaction when an - * operation overflows. - * - * Using this library instead of the unchecked operations eliminates an entire - * class of bugs, so it's recommended to use it always. - */ -library SafeMath { - /** - * @dev Returns the addition of two unsigned integers, reverting on - * overflow. - * - * Counterpart to Solidity's `+` operator. - * - * Requirements: - * - * - Addition cannot overflow. - */ - function add(uint256 a, uint256 b) internal pure returns (uint256) { - uint256 c = a + b; - require(c >= a, "SafeMath: addition overflow"); - - return c; - } - - /** - * @dev Returns the subtraction of two unsigned integers, reverting on - * overflow (when the result is negative). - * - * Counterpart to Solidity's `-` operator. - * - * Requirements: - * - * - Subtraction cannot overflow. - */ - function sub(uint256 a, uint256 b) internal pure returns (uint256) { - return sub(a, b, "SafeMath: subtraction overflow"); - } - - /** - * @dev Returns the subtraction of two unsigned integers, reverting with custom message on - * overflow (when the result is negative). - * - * Counterpart to Solidity's `-` operator. - * - * Requirements: - * - * - Subtraction cannot overflow. - */ - function sub( - uint256 a, - uint256 b, - string memory errorMessage - ) internal pure returns (uint256) { - require(b <= a, errorMessage); - uint256 c = a - b; - - return c; - } - - /** - * @dev Returns the multiplication of two unsigned integers, reverting on - * overflow. - * - * Counterpart to Solidity's `*` operator. - * - * Requirements: - * - * - Multiplication cannot overflow. - */ - function mul(uint256 a, uint256 b) internal pure returns (uint256) { - // Gas optimization: this is cheaper than requiring 'a' not being zero, but the - // benefit is lost if 'b' is also tested. - // See: https://github.com/OpenZeppelin/openzeppelin-contracts/pull/522 - if (a == 0) { - return 0; - } - - uint256 c = a * b; - require(c / a == b, "SafeMath: multiplication overflow"); - - return c; - } - - /** - * @dev Returns the integer division of two unsigned integers. Reverts on - * division by zero. The result is rounded towards zero. - * - * Counterpart to Solidity's `/` operator. Note: this function uses a - * `revert` opcode (which leaves remaining gas untouched) while Solidity - * uses an invalid opcode to revert (consuming all remaining gas). - * - * Requirements: - * - * - The divisor cannot be zero. - */ - function div(uint256 a, uint256 b) internal pure returns (uint256) { - return div(a, b, "SafeMath: division by zero"); - } - - /** - * @dev Returns the integer division of two unsigned integers. Reverts with custom message on - * division by zero. The result is rounded towards zero. - * - * Counterpart to Solidity's `/` operator. Note: this function uses a - * `revert` opcode (which leaves remaining gas untouched) while Solidity - * uses an invalid opcode to revert (consuming all remaining gas). - * - * Requirements: - * - * - The divisor cannot be zero. - */ - function div( - uint256 a, - uint256 b, - string memory errorMessage - ) internal pure returns (uint256) { - require(b > 0, errorMessage); - uint256 c = a / b; - // assert(a == b * c + a % b); // There is no case in which this doesn't hold - - return c; - } - - /** - * @dev Returns the remainder of dividing two unsigned integers. (unsigned integer modulo), - * Reverts when dividing by zero. - * - * Counterpart to Solidity's `%` operator. This function uses a `revert` - * opcode (which leaves remaining gas untouched) while Solidity uses an - * invalid opcode to revert (consuming all remaining gas). - * - * Requirements: - * - * - The divisor cannot be zero. - */ - function mod(uint256 a, uint256 b) internal pure returns (uint256) { - return mod(a, b, "SafeMath: modulo by zero"); - } - - /** - * @dev Returns the remainder of dividing two unsigned integers. (unsigned integer modulo), - * Reverts with custom message when dividing by zero. - * - * Counterpart to Solidity's `%` operator. This function uses a `revert` - * opcode (which leaves remaining gas untouched) while Solidity uses an - * invalid opcode to revert (consuming all remaining gas). - * - * Requirements: - * - * - The divisor cannot be zero. - */ - function mod( - uint256 a, - uint256 b, - string memory errorMessage - ) internal pure returns (uint256) { - require(b != 0, errorMessage); - return a % b; - } - - // babylonian method (https://en.wikipedia.org/wiki/Methods_of_computing_square_roots#Babylonian_method) - function sqrrt(uint256 a) internal pure returns (uint256 c) { - if (a > 3) { - c = a; - uint256 b = add(div(a, 2), 1); - while (b < c) { - c = b; - b = div(add(div(a, b), b), 2); - } - } else if (a != 0) { - c = 1; - } - } - - /* - * Expects percentage to be trailed by 00, - */ - function percentageAmount(uint256 total_, uint8 percentage_) internal pure returns (uint256 percentAmount_) { - return div(mul(total_, percentage_), 1000); - } - - /* - * Expects percentage to be trailed by 00, - */ - function substractPercentage(uint256 total_, uint8 percentageToSub_) internal pure returns (uint256 result_) { - return sub(total_, div(mul(total_, percentageToSub_), 1000)); - } - - function percentageOfTotal(uint256 part_, uint256 total_) internal pure returns (uint256 percent_) { - return div(mul(part_, 100), total_); - } - - /** - * Taken from Hypersonic https://github.com/M2629/HyperSonic/blob/main/Math.sol - * @dev Returns the average of two numbers. The result is rounded towards - * zero. - */ - function average(uint256 a, uint256 b) internal pure returns (uint256) { - // (a + b) / 2 can overflow, so we distribute - return (a / 2) + (b / 2) + (((a % 2) + (b % 2)) / 2); - } - - function quadraticPricing(uint256 payment_, uint256 multiplier_) internal pure returns (uint256) { - return sqrrt(mul(multiplier_, payment_)); - } - - function bondingCurve(uint256 supply_, uint256 multiplier_) internal pure returns (uint256) { - return mul(multiplier_, supply_); - } -} - -// OpenZeppelin Contracts (last updated v4.7.0) (token/ERC20/utils/SafeERC20.sol) - - - - - -// OpenZeppelin Contracts v4.4.1 (token/ERC20/extensions/draft-IERC20Permit.sol) - - - -/** - * @dev Interface of the ERC20 Permit extension allowing approvals to be made via signatures, as defined in - * https://eips.ethereum.org/EIPS/eip-2612[EIP-2612]. - * - * Adds the {permit} method, which can be used to change an account's ERC20 allowance (see {IERC20-allowance}) by - * presenting a message signed by the account. By not relying on {IERC20-approve}, the token holder account doesn't - * need to send a transaction, and thus is not required to hold Ether at all. - */ -interface IERC20Permit { - /** - * @dev Sets `value` as the allowance of `spender` over ``owner``'s tokens, - * given ``owner``'s signed approval. - * - * IMPORTANT: The same issues {IERC20-approve} has related to transaction - * ordering also apply here. - * - * Emits an {Approval} event. - * - * Requirements: - * - * - `spender` cannot be the zero address. - * - `deadline` must be a timestamp in the future. - * - `v`, `r` and `s` must be a valid `secp256k1` signature from `owner` - * over the EIP712-formatted function arguments. - * - the signature must use ``owner``'s current nonce (see {nonces}). - * - * For more information on the signature format, see the - * https://eips.ethereum.org/EIPS/eip-2612#specification[relevant EIP - * section]. - */ - function permit( - address owner, - address spender, - uint256 value, - uint256 deadline, - uint8 v, - bytes32 r, - bytes32 s - ) external; - - /** - * @dev Returns the current nonce for `owner`. This value must be - * included whenever a signature is generated for {permit}. - * - * Every successful call to {permit} increases ``owner``'s nonce by one. This - * prevents a signature from being used multiple times. - */ - function nonces(address owner) external view returns (uint256); - - /** - * @dev Returns the domain separator used in the encoding of the signature for {permit}, as defined by {EIP712}. - */ - // solhint-disable-next-line func-name-mixedcase - function DOMAIN_SEPARATOR() external view returns (bytes32); -} - - - -/** - * @title SafeERC20 - * @dev Wrappers around ERC20 operations that throw on failure (when the token - * contract returns false). Tokens that return no value (and instead revert or - * throw on failure) are also supported, non-reverting calls are assumed to be - * successful. - * To use this library you can add a `using SafeERC20 for IERC20;` statement to your contract, - * which allows you to call the safe operations as `token.safeTransfer(...)`, etc. - */ -library SafeERC20 { - using Address for address; - - function safeTransfer( - IERC20 token, - address to, - uint256 value - ) internal { - _callOptionalReturn(token, abi.encodeWithSelector(token.transfer.selector, to, value)); - } - - function safeTransferFrom( - IERC20 token, - address from, - address to, - uint256 value - ) internal { - _callOptionalReturn(token, abi.encodeWithSelector(token.transferFrom.selector, from, to, value)); - } - - /** - * @dev Deprecated. This function has issues similar to the ones found in - * {IERC20-approve}, and its usage is discouraged. - * - * Whenever possible, use {safeIncreaseAllowance} and - * {safeDecreaseAllowance} instead. - */ - function safeApprove( - IERC20 token, - address spender, - uint256 value - ) internal { - // safeApprove should only be called when setting an initial allowance, - // or when resetting it to zero. To increase and decrease it, use - // 'safeIncreaseAllowance' and 'safeDecreaseAllowance' - require( - (value == 0) || (token.allowance(address(this), spender) == 0), - "SafeERC20: approve from non-zero to non-zero allowance" - ); - _callOptionalReturn(token, abi.encodeWithSelector(token.approve.selector, spender, value)); - } - - function safeIncreaseAllowance( - IERC20 token, - address spender, - uint256 value - ) internal { - uint256 newAllowance = token.allowance(address(this), spender) + value; - _callOptionalReturn(token, abi.encodeWithSelector(token.approve.selector, spender, newAllowance)); - } - - function safeDecreaseAllowance( - IERC20 token, - address spender, - uint256 value - ) internal { - unchecked { - uint256 oldAllowance = token.allowance(address(this), spender); - require(oldAllowance >= value, "SafeERC20: decreased allowance below zero"); - uint256 newAllowance = oldAllowance - value; - _callOptionalReturn(token, abi.encodeWithSelector(token.approve.selector, spender, newAllowance)); - } - } - - function safePermit( - IERC20Permit token, - address owner, - address spender, - uint256 value, - uint256 deadline, - uint8 v, - bytes32 r, - bytes32 s - ) internal { - uint256 nonceBefore = token.nonces(owner); - token.permit(owner, spender, value, deadline, v, r, s); - uint256 nonceAfter = token.nonces(owner); - require(nonceAfter == nonceBefore + 1, "SafeERC20: permit did not succeed"); - } - - /** - * @dev Imitates a Solidity high-level call (i.e. a regular function call to a contract), relaxing the requirement - * on the return value: the return value is optional (but if data is returned, it must not be false). - * @param token The token targeted by the call. - * @param data The call data (encoded using abi.encode or one of its variants). - */ - function _callOptionalReturn(IERC20 token, bytes memory data) private { - // We need to perform a low level call here, to bypass Solidity's return data size checking mechanism, since - // we're implementing it ourselves. We use {Address.functionCall} to perform this call, which verifies that - // the target address contains contract code and also asserts for success in the low-level call. - - bytes memory returndata = address(token).functionCall(data, "SafeERC20: low-level call failed"); - if (returndata.length > 0) { - // Return data is optional - require(abi.decode(returndata, (bool)), "SafeERC20: ERC20 operation did not succeed"); - } - } -} - - - - - - - - - - - - - - -/** - * @dev Provides information about the current execution context, including the - * sender of the transaction and its data. While these are generally available - * via msg.sender and msg.data, they should not be accessed in such a direct - * manner, since when dealing with meta-transactions the account sending and - * paying for execution may not be the actual sender (as far as an application - * is concerned). - * - * This contract is only required for intermediate, library-like contracts. - */ -abstract contract Context { - function _msgSender() internal view virtual returns (address) { - return msg.sender; - } - - function _msgData() internal view virtual returns (bytes calldata) { - return msg.data; - } -} - - -/** - * @dev Contract module which provides a basic access control mechanism, where - * there is an account (an owner) that can be granted exclusive access to - * specific functions. - * - * By default, the owner account will be the one that deploys the contract. This - * can later be changed with {transferOwnership}. - * - * This module is used through inheritance. It will make available the modifier - * `onlyOwner`, which can be applied to your functions to restrict their use to - * the owner. - */ -abstract contract Ownable is Context { - address private _owner; - - event OwnershipTransferred(address indexed previousOwner, address indexed newOwner); - - /** - * @dev Initializes the contract setting the deployer as the initial owner. - */ - constructor() { - _transferOwnership(_msgSender()); - } - - /** - * @dev Throws if called by any account other than the owner. - */ - modifier onlyOwner() { - _checkOwner(); - _; - } - - /** - * @dev Returns the address of the current owner. - */ - function owner() public view virtual returns (address) { - return _owner; - } - - /** - * @dev Throws if the sender is not the owner. - */ - function _checkOwner() internal view virtual { - require(owner() == _msgSender(), "Ownable: caller is not the owner"); - } - - /** - * @dev Leaves the contract without owner. It will not be possible to call - * `onlyOwner` functions anymore. Can only be called by the current owner. - * - * NOTE: Renouncing ownership will leave the contract without an owner, - * thereby removing any functionality that is only available to the owner. - */ - function renounceOwnership() public virtual onlyOwner { - _transferOwnership(address(0)); - } - - /** - * @dev Transfers ownership of the contract to a new account (`newOwner`). - * Can only be called by the current owner. - */ - function transferOwnership(address newOwner) public virtual onlyOwner { - require(newOwner != address(0), "Ownable: new owner is the zero address"); - _transferOwnership(newOwner); - } - - /** - * @dev Transfers ownership of the contract to a new account (`newOwner`). - * Internal function without access restriction. - */ - function _transferOwnership(address newOwner) internal virtual { - address oldOwner = _owner; - _owner = newOwner; - emit OwnershipTransferred(oldOwner, newOwner); - } -} - - -contract Operator is Ownable { - address public operator; - uint256 constant baseRate = 10000; - - modifier onlyOperator { - require(msg.sender == owner() || msg.sender == operator, "no permission"); - _; - } - - function setOperator(address operator_) external onlyOwner { - operator = operator_; - } - - - function getCurrTime() external view returns(uint256) { - return block.timestamp; - } - - function getBlockNum() external view returns(uint256) { - return block.number; - } - -} - - - - - -/** - * @dev Library for managing - * https://en.wikipedia.org/wiki/Set_(abstract_data_type)[sets] of primitive - * types. - * - * Sets have the following properties: - * - * - Elements are added, removed, and checked for existence in constant time - * (O(1)). - * - Elements are enumerated in O(n). No guarantees are made on the ordering. - * - * ``` - * contract Example { - * // Add the library methods - * using EnumerableSet for EnumerableSet.AddressSet; - * - * // Declare a set state variable - * EnumerableSet.AddressSet private mySet; - * } - * ``` - * - * As of v3.3.0, sets of type `bytes32` (`Bytes32Set`), `address` (`AddressSet`) - * and `uint256` (`UintSet`) are supported. - * - * [WARNING] - * ==== - * Trying to delete such a structure from storage will likely result in data corruption, rendering the structure unusable. - * See https://github.com/ethereum/solidity/pull/11843[ethereum/solidity#11843] for more info. - * - * In order to clean an EnumerableSet, you can either remove all elements one by one or create a fresh instance using an array of EnumerableSet. - * ==== - */ - -library EnumerableSet { - // To implement this library for multiple types with as little code - // repetition as possible, we write it in terms of a generic Set type with - // bytes32 values. - // The Set implementation uses private functions, and user-facing - // implementations (such as AddressSet) are just wrappers around the - // underlying Set. - // This means that we can only create new EnumerableSets for types that fit - // in bytes32. - - struct Set { - // Storage of set values - bytes32[] _values; - // Position of the value in the `values` array, plus 1 because index 0 - // means a value is not in the set. - mapping(bytes32 => uint256) _indexes; - } - - /** - * @dev Add a value to a set. O(1). - * - * Returns true if the value was added to the set, that is if it was not - * already present. - */ - function _add(Set storage set, bytes32 value) private returns (bool) { - if (!_contains(set, value)) { - set._values.push(value); - // The value is stored at length-1, but we add 1 to all indexes - // and use 0 as a sentinel value - set._indexes[value] = set._values.length; - return true; - } else { - return false; - } - } - - /** - * @dev Removes a value from a set. O(1). - * - * Returns true if the value was removed from the set, that is if it was - * present. - */ - function _remove(Set storage set, bytes32 value) private returns (bool) { - // We read and store the value's index to prevent multiple reads from the same storage slot - uint256 valueIndex = set._indexes[value]; - - if (valueIndex != 0) { - // Equivalent to contains(set, value) - // To delete an element from the _values array in O(1), we swap the element to delete with the last one in - // the array, and then remove the last element (sometimes called as 'swap and pop'). - // This modifies the order of the array, as noted in {at}. - - uint256 toDeleteIndex = valueIndex - 1; - uint256 lastIndex = set._values.length - 1; - - if (lastIndex != toDeleteIndex) { - bytes32 lastValue = set._values[lastIndex]; - - // Move the last value to the index where the value to delete is - set._values[toDeleteIndex] = lastValue; - // Update the index for the moved value - set._indexes[lastValue] = valueIndex; // Replace lastValue's index to valueIndex - } - - // Delete the slot where the moved value was stored - set._values.pop(); - - // Delete the index for the deleted slot - delete set._indexes[value]; - - return true; - } else { - return false; - } - } - - /** - * @dev Returns true if the value is in the set. O(1). - */ - function _contains(Set storage set, bytes32 value) private view returns (bool) { - return set._indexes[value] != 0; - } - - /** - * @dev Returns the number of values on the set. O(1). - */ - function _length(Set storage set) private view returns (uint256) { - return set._values.length; - } - - /** - * @dev Returns the value stored at position `index` in the set. O(1). - * - * Note that there are no guarantees on the ordering of values inside the - * array, and it may change when more values are added or removed. - * - * Requirements: - * - * - `index` must be strictly less than {length}. - */ - function _at(Set storage set, uint256 index) private view returns (bytes32) { - return set._values[index]; - } - - /** - * @dev Return the entire set in an array - * - * WARNING: This operation will copy the entire storage to memory, which can be quite expensive. This is designed - * to mostly be used by view accessors that are queried without any gas fees. Developers should keep in mind that - * this function has an unbounded cost, and using it as part of a state-changing function may render the function - * uncallable if the set grows to a point where copying to memory consumes too much gas to fit in a block. - */ - function _values(Set storage set) private view returns (bytes32[] memory) { - return set._values; - } - - // Bytes32Set - - struct Bytes32Set { - Set _inner; - } - - /** - * @dev Add a value to a set. O(1). - * - * Returns true if the value was added to the set, that is if it was not - * already present. - */ - function add(Bytes32Set storage set, bytes32 value) internal returns (bool) { - return _add(set._inner, value); - } - - /** - * @dev Removes a value from a set. O(1). - * - * Returns true if the value was removed from the set, that is if it was - * present. - */ - function remove(Bytes32Set storage set, bytes32 value) internal returns (bool) { - return _remove(set._inner, value); - } - - /** - * @dev Returns true if the value is in the set. O(1). - */ - function contains(Bytes32Set storage set, bytes32 value) internal view returns (bool) { - return _contains(set._inner, value); - } - - /** - * @dev Returns the number of values in the set. O(1). - */ - function length(Bytes32Set storage set) internal view returns (uint256) { - return _length(set._inner); - } - - /** - * @dev Returns the value stored at position `index` in the set. O(1). - * - * Note that there are no guarantees on the ordering of values inside the - * array, and it may change when more values are added or removed. - * - * Requirements: - * - * - `index` must be strictly less than {length}. - */ - function at(Bytes32Set storage set, uint256 index) internal view returns (bytes32) { - return _at(set._inner, index); - } - - /** - * @dev Return the entire set in an array - * - * WARNING: This operation will copy the entire storage to memory, which can be quite expensive. This is designed - * to mostly be used by view accessors that are queried without any gas fees. Developers should keep in mind that - * this function has an unbounded cost, and using it as part of a state-changing function may render the function - * uncallable if the set grows to a point where copying to memory consumes too much gas to fit in a block. - */ - function values(Bytes32Set storage set) internal view returns (bytes32[] memory) { - return _values(set._inner); - } - - // AddressSet - - struct AddressSet { - Set _inner; - } - - /** - * @dev Add a value to a set. O(1). - * - * Returns true if the value was added to the set, that is if it was not - * already present. - */ - function add(AddressSet storage set, address value) internal returns (bool) { - return _add(set._inner, bytes32(uint256(uint160(value)))); - } - - /** - * @dev Removes a value from a set. O(1). - * - * Returns true if the value was removed from the set, that is if it was - * present. - */ - function remove(AddressSet storage set, address value) internal returns (bool) { - return _remove(set._inner, bytes32(uint256(uint160(value)))); - } - - /** - * @dev Returns true if the value is in the set. O(1). - */ - function contains(AddressSet storage set, address value) internal view returns (bool) { - return _contains(set._inner, bytes32(uint256(uint160(value)))); - } - - /** - * @dev Returns the number of values in the set. O(1). - */ - function length(AddressSet storage set) internal view returns (uint256) { - return _length(set._inner); - } - - /** - * @dev Returns the value stored at position `index` in the set. O(1). - * - * Note that there are no guarantees on the ordering of values inside the - * array, and it may change when more values are added or removed. - * - * Requirements: - * - * - `index` must be strictly less than {length}. - */ - function at(AddressSet storage set, uint256 index) internal view returns (address) { - return address(uint160(uint256(_at(set._inner, index)))); - } - - /** - * @dev Return the entire set in an array - * - * WARNING: This operation will copy the entire storage to memory, which can be quite expensive. This is designed - * to mostly be used by view accessors that are queried without any gas fees. Developers should keep in mind that - * this function has an unbounded cost, and using it as part of a state-changing function may render the function - * uncallable if the set grows to a point where copying to memory consumes too much gas to fit in a block. - */ - function values(AddressSet storage set) internal view returns (address[] memory) { - bytes32[] memory store = _values(set._inner); - address[] memory result; - - /// @solidity memory-safe-assembly - assembly { - result := store - } - - return result; - } - - // UintSet - - struct UintSet { - Set _inner; - } - - /** - * @dev Add a value to a set. O(1). - * - * Returns true if the value was added to the set, that is if it was not - * already present. - */ - function add(UintSet storage set, uint256 value) internal returns (bool) { - return _add(set._inner, bytes32(value)); - } - - /** - * @dev Removes a value from a set. O(1). - * - * Returns true if the value was removed from the set, that is if it was - * present. - */ - function remove(UintSet storage set, uint256 value) internal returns (bool) { - return _remove(set._inner, bytes32(value)); - } - - /** - * @dev Returns true if the value is in the set. O(1). - */ - function contains(UintSet storage set, uint256 value) internal view returns (bool) { - return _contains(set._inner, bytes32(value)); - } - - /** - * @dev Returns the number of values on the set. O(1). - */ - function length(UintSet storage set) internal view returns (uint256) { - return _length(set._inner); - } - - /** - * @dev Returns the value stored at position `index` in the set. O(1). - * - * Note that there are no guarantees on the ordering of values inside the - * array, and it may change when more values are added or removed. - * - * Requirements: - * - * - `index` must be strictly less than {length}. - */ - function at(UintSet storage set, uint256 index) internal view returns (uint256) { - return uint256(_at(set._inner, index)); - } - - /** - * @dev Return the entire set in an array - * - * WARNING: This operation will copy the entire storage to memory, which can be quite expensive. This is designed - * to mostly be used by view accessors that are queried without any gas fees. Developers should keep in mind that - * this function has an unbounded cost, and using it as part of a state-changing function may render the function - * uncallable if the set grows to a point where copying to memory consumes too much gas to fit in a block. - */ - function values(UintSet storage set) internal view returns (uint256[] memory) { - bytes32[] memory store = _values(set._inner); - uint256[] memory result; - - /// @solidity memory-safe-assembly - assembly { - result := store - } - - return result; - } -} - - -contract ActivityPool is Operator { - using SafeMath for uint256; - using SafeERC20 for IERC20; - using EnumerableSet for EnumerableSet.AddressSet; - using EnumerableSet for EnumerableSet.UintSet; - - event AddNewAct(uint256 id); - event Bet(address user, uint256 pID, uint256 bType, uint256 amount, uint256 time); - event SetPrize(uint256 pID, uint256 bType); - event Claim(address user, uint256 pID, uint256 bType, uint256 amount); - event RemovePeriodAct(uint256 pID); - - uint256 public constant muti = 1e18; - uint256 public periodID; - uint256 public betID; - - struct UserInfo { - address user; - uint256 pID; - uint256 amount; - uint256 betTime; - uint256 bType; - uint256 claimAmount; - } - - struct ActInfo { - string name; - string aName; - string bName; - address rewardToken; - uint256 startTime; - uint256 endTime; - uint256 minAmount; - uint256 maxAmount; - uint256 aAmount; - uint256 bAmount; - uint256 winType; - bool isBet; - } - - struct TimeInfo { - uint256 time; - uint256 aAmount; - uint256 bAmount; - } - - struct BestInfo { - address aUser; - address bUser; - uint256 aBet; - uint256 bBet; - } - - mapping(uint256 => BestInfo) bestInfo; - mapping(uint256 => uint256) public timeID; - mapping(uint256 => mapping(uint256 => TimeInfo)) public timeInfo; - mapping(address => mapping(uint256 => uint256)) public userBet; - mapping(uint256 => UserInfo) public betInfo; - mapping(uint256 => uint256) public perAmount; - mapping(uint256 => ActInfo) public actInfo; - mapping(uint256 => mapping(uint256 => string)) public descripName; - - mapping(address => EnumerableSet.UintSet) userPid; - mapping(uint256 => EnumerableSet.AddressSet) aUsers; - mapping(uint256 => EnumerableSet.AddressSet) bUsers; - EnumerableSet.UintSet activePeriod; - EnumerableSet.UintSet removePeriod; - - function addNewAct( - string memory name, - string memory aName, - string memory bName, - address token, - uint256 startTime, - uint256 endTime, - uint256 minAmount, - uint256 maxAmount - ) external onlyOperator { - - checkAdd(msg.sender, startTime, endTime, minAmount, maxAmount); - uint256 id = ++periodID; - actInfo[id].name = name; - actInfo[id].aName = aName; - actInfo[id].bName = bName; - actInfo[id].startTime = startTime; - actInfo[id].endTime = endTime; - actInfo[id].minAmount = minAmount; - actInfo[id].maxAmount = maxAmount; - actInfo[id].rewardToken = token; - descripName[id][1] = aName; - descripName[id][2] = bName; - activePeriod.add(id); - - emit AddNewAct(id); - } - - - function removePeriodAct(uint256 pID) external onlyOperator { - checkRemove(pID); - - activePeriod.remove(pID); - removePeriod.add(pID); - - emit RemovePeriodAct(pID); - } - - - function bet(uint256 pID, uint256 bType, uint256 amount) external payable { - checkBet(msg.sender, pID, bType, amount); - if(actInfo[pID].rewardToken == address(0)) { - require(msg.value == amount, "value err"); - } else { - require(msg.value == 0, "value amount err"); - } - - if(bType == 1) { - if(amount > bestInfo[pID].aBet) { - bestInfo[pID].aUser = msg.sender; - bestInfo[pID].aBet = amount; - } - } else { - if(amount > bestInfo[pID].bBet) { - bestInfo[pID].bUser = msg.sender; - bestInfo[pID].bBet = amount; - } - } - - userPid[msg.sender].add(pID); - uint256 id = ++betID; - userBet[msg.sender][pID] = id; - - if(bType == 1) { - aUsers[pID].add(msg.sender); - actInfo[pID].aAmount = actInfo[pID].aAmount.add(amount); - } else { - bUsers[pID].add(msg.sender); - actInfo[pID].bAmount = actInfo[pID].bAmount.add(amount); - } - - actInfo[pID].isBet = true; - betInfo[id].user = msg.sender; - betInfo[id].pID = pID; - betInfo[id].amount = amount; - betInfo[id].betTime = block.timestamp; - betInfo[id].bType = bType; - - uint256 tID = ++timeID[pID]; - timeInfo[pID][tID].time = block.timestamp; - timeInfo[pID][tID].aAmount = actInfo[pID].aAmount; - timeInfo[pID][tID].bAmount = actInfo[pID].bAmount; - - if(actInfo[pID].rewardToken != address(0)) { - IERC20(actInfo[pID].rewardToken).safeTransferFrom(msg.sender, address(this), amount); - } - emit Bet(msg.sender, pID, bType, amount, betInfo[id].betTime); - } - - function setPrize(uint256 pID, uint256 bType) external onlyOperator { - checkSetPrize(msg.sender, pID, bType); - - if(block.timestamp <= actInfo[pID].startTime) { - actInfo[pID].startTime = block.timestamp; - - } - actInfo[pID].endTime = block.timestamp; - - actInfo[pID].winType = bType; - perAmount[pID] = getPerAmount(pID, bType); - - emit SetPrize(pID, bType); - } - - function recive() public payable {} - - function claim(uint256 pID) external { - uint256 amount = checkClaim(msg.sender, pID); - - uint256 id = userBet[msg.sender][pID]; - betInfo[id].claimAmount = amount; - if(actInfo[pID].rewardToken != address(0)) { - IERC20(actInfo[pID].rewardToken).safeTransfer(msg.sender, amount); - } else { - payable(msg.sender).transfer(amount); - } - - emit Claim(msg.sender, pID, betInfo[id].bType, amount); - } - - function checkClaim(address user, uint256 pID) public view returns(uint256 amount) { - require(userPid[user].contains(pID), "not bet"); - uint256 id = userBet[user][pID]; - require(betInfo[id].user == user, "not user"); - require(actInfo[pID].winType != 0, "not prize"); - require(betInfo[id].claimAmount == 0, "has claim"); - - if(actInfo[pID].winType != 3) { - require(actInfo[pID].winType == betInfo[id].bType, "not right"); - amount = perAmount[pID].mul(betInfo[id].amount).div(muti); - require(amount > 0, "no amount"); - } else { - amount = betInfo[id].amount; - } - - return amount; - } - - function getActualRate( - address user, - uint256 pID, - uint256 bType, - uint256 amount - ) external view returns(uint256, uint256, bool) { - if(bType < 1 || bType > 2 || !activePeriod.contains(pID)) { - return (0, 0, false); - } else if(userBet[user][pID] != 0 || actInfo[pID].winType != 0 || amount == 0) { - (uint256 ra, uint256 rb) = getRate(pID, timeID[pID]); - return (ra, rb, false); - } else { - (uint256 aAmount, uint256 bAmount) = (actInfo[pID].aAmount, actInfo[pID].bAmount); - if(bType == 1) { - aAmount = aAmount.add(amount); - } else { - bAmount = bAmount.add(amount); - } - - uint256 total = aAmount.add(bAmount); - if(bAmount == 0 && aAmount != 0) { - return (muti, 0, true); - } - if(bAmount != 0 && aAmount == 0) { - return (0, muti, true); - } - return (total.mul(muti).div(aAmount), total.mul(muti).div(bAmount), true); - } - } - - function getRate(uint256 pID, uint256 tID) public view returns(uint256, uint256) { - (uint256 aAmount, uint256 bAmount) = (timeInfo[pID][tID].aAmount, timeInfo[pID][tID].bAmount); - uint256 total = aAmount.add(bAmount); - if(total == 0) { - return (0, 0); - } - if(bAmount == 0 && aAmount != 0) { - return (muti, 0); - } - if(bAmount != 0 && aAmount == 0) { - return (0, muti); - } - return (total.mul(muti).div(aAmount), total.mul(muti).div(bAmount)); - } - - function getBestInfo(uint256 pID) - external - view - returns(address aUser, address bUser, uint256 aBet, uint256 bBet, uint256 aReward, uint256 bReward) - { - aUser = bestInfo[pID].aUser; - bUser = bestInfo[pID].bUser; - aBet = bestInfo[pID].aBet; - bBet = bestInfo[pID].bBet; - aReward = getPerAmount(pID, 1).mul(aBet).div(muti); - bReward = getPerAmount(pID, 2).mul(bBet).div(muti); - } - - function getPerAmount(uint256 pID, uint256 bType) public view returns(uint256) { - uint256 total = actInfo[pID].aAmount.add(actInfo[pID].bAmount); - if(total == 0) { - return 0; - } - - if(actInfo[pID].winType == 3) { - return muti; - } - - if(bType == 1) { - if(actInfo[pID].aAmount == 0 || actInfo[pID].winType == 2) { - return 0; - } - return total.mul(muti).div(actInfo[pID].aAmount); - } - - if(bType == 2) { - if(actInfo[pID].bAmount == 0 || actInfo[pID].winType == 1) { - return 0; - } - return total.mul(muti).div(actInfo[pID].bAmount); - } - - return 0; - - } - - function checkSetPrize(address user, uint256 pID, uint256 bType) public view returns(bool) { - require(user == owner() || user == operator, "no permission"); - require(bType > 0 && bType <= 3, "type err"); - require(activePeriod.contains(pID), "not active"); - require(actInfo[pID].winType == 0, "has set"); - - return true; - } - - function checkBet( - address user, - uint256 pID, - uint256 bType, - uint256 amount - ) public view returns(bool) { - require(activePeriod.contains(pID), "not active"); - require(actInfo[pID].startTime <= block.timestamp, "not start"); - require(actInfo[pID].endTime > block.timestamp, "has end"); - require(!userPid[user].contains(pID), "has bet"); - require(bType > 0 && bType < 3, "type err"); - require(amount >= actInfo[pID].minAmount && amount <= actInfo[pID].maxAmount, "amount err"); - if(actInfo[pID].rewardToken != address(0)) { - require(IERC20(actInfo[pID].rewardToken).allowance(user, address(this)) >= amount, "not approve enough"); - require(IERC20(actInfo[pID].rewardToken).balanceOf(user) >= amount, "not enough"); - } else { - require(user.balance >= amount, "main token err"); - } - - return true; - } - - - function checkRemove(uint256 pID) public view returns(bool) { - require(activePeriod.contains(pID), "not in"); - require(!actInfo[pID].isBet, "has bet"); - - return true; - } - - function checkAdd( - address user, - uint256 startTime, - uint256 endTime, - uint256 minAmount, - uint256 maxAmount - ) public view returns(bool) { - require(user == owner() || user == operator, "no permission"); - require(startTime > block.timestamp, "startTime err"); - require(endTime > startTime, "endTime err"); - require(minAmount > 0 && maxAmount > minAmount, "amount err"); - - return true; - } - - function getStatus(uint256 pID) external view returns(uint256) { - if(!removePeriod.contains(pID) && !activePeriod.contains(pID)) { - return 5; - } else if(removePeriod.contains(pID)) { - return 6; - } else if(block.timestamp < actInfo[pID].startTime) { - return 1; - } else if ( - actInfo[pID].startTime <= block.timestamp && - actInfo[pID].endTime > block.timestamp - ) { - return 2; - } else if (actInfo[pID].endTime <= block.timestamp && actInfo[pID].winType == 0){ - return 3; - } else if(actInfo[pID].winType != 0) { - return 4; - } - return 0; - } - - function getUserPidNum(address user) external view returns(uint256) { - return userPid[user].length(); - } - - function getUserPid(address user, uint256 index) external view returns(uint256) { - return userPid[user].at(index); - } - - function getAUsersNum(uint256 pID) external view returns(uint256) { - return aUsers[pID].length(); - } - - function getAUsers(uint256 pID, uint256 index) external view returns(address) { - return aUsers[pID].at(index); - } - - function getBUsersNum(uint256 pID) external view returns(uint256) { - return bUsers[pID].length(); - } - - function getBUsers(uint256 pID, uint256 index) external view returns(address) { - return bUsers[pID].at(index); - } - - function getActivePeriodNum() external view returns(uint256) { - return activePeriod.length(); - } - - function getActivePeriod(uint256 index) external view returns(uint256) { - return activePeriod.at(index); - } - - function getRemovePeriodNum() external view returns(uint256) { - return removePeriod.length(); - } - - function getRemovePeriod(uint256 index) external view returns(uint256) { - return removePeriod.at(index); - } -} \ No newline at end of file diff --git a/app/api/uploads/ActivityPool-1729789257596-770519629.sol b/app/api/uploads/ActivityPool-1729789257596-770519629.sol deleted file mode 100644 index daf3372..0000000 --- a/app/api/uploads/ActivityPool-1729789257596-770519629.sol +++ /dev/null @@ -1,1648 +0,0 @@ -// SPDX-License-Identifier: MIT -// OpenZeppelin Contracts (last updated v4.7.0) (utils/Address.sol) - -pragma solidity ^0.8.1; - -/** - * @dev Collection of functions related to the address type - */ -library Address { - /** - * @dev Returns true if `account` is a contract. - * - * [IMPORTANT] - * ==== - * It is unsafe to assume that an address for which this function returns - * false is an externally-owned account (EOA) and not a contract. - * - * Among others, `isContract` will return false for the following - * types of addresses: - * - * - an externally-owned account - * - a contract in construction - * - an address where a contract will be created - * - an address where a contract lived, but was destroyed - * ==== - * - * [IMPORTANT] - * ==== - * You shouldn't rely on `isContract` to protect against flash loan attacks! - * - * Preventing calls from contracts is highly discouraged. It breaks composability, breaks support for smart wallets - * like Gnosis Safe, and does not provide security since it can be circumvented by calling from a contract - * constructor. - * ==== - */ - function isContract(address account) internal view returns (bool) { - // This method relies on extcodesize/address.code.length, which returns 0 - // for contracts in construction, since the code is only stored at the end - // of the constructor execution. - - return account.code.length > 0; - } - - /** - * @dev Replacement for Solidity's `transfer`: sends `amount` wei to - * `recipient`, forwarding all available gas and reverting on errors. - * - * https://eips.ethereum.org/EIPS/eip-1884[EIP1884] increases the gas cost - * of certain opcodes, possibly making contracts go over the 2300 gas limit - * imposed by `transfer`, making them unable to receive funds via - * `transfer`. {sendValue} removes this limitation. - * - * https://diligence.consensys.net/posts/2019/09/stop-using-soliditys-transfer-now/[Learn more]. - * - * IMPORTANT: because control is transferred to `recipient`, care must be - * taken to not create reentrancy vulnerabilities. Consider using - * {ReentrancyGuard} or the - * https://solidity.readthedocs.io/en/v0.5.11/security-considerations.html#use-the-checks-effects-interactions-pattern[checks-effects-interactions pattern]. - */ - function sendValue(address payable recipient, uint256 amount) internal { - require(address(this).balance >= amount, "Address: insufficient balance"); - - (bool success, ) = recipient.call{value: amount}(""); - require(success, "Address: unable to send value, recipient may have reverted"); - } - - /** - * @dev Performs a Solidity function call using a low level `call`. A - * plain `call` is an unsafe replacement for a function call: use this - * function instead. - * - * If `target` reverts with a revert reason, it is bubbled up by this - * function (like regular Solidity function calls). - * - * Returns the raw returned data. To convert to the expected return value, - * use https://solidity.readthedocs.io/en/latest/units-and-global-variables.html?highlight=abi.decode#abi-encoding-and-decoding-functions[`abi.decode`]. - * - * Requirements: - * - * - `target` must be a contract. - * - calling `target` with `data` must not revert. - * - * _Available since v3.1._ - */ - function functionCall(address target, bytes memory data) internal returns (bytes memory) { - return functionCallWithValue(target, data, 0, "Address: low-level call failed"); - } - - /** - * @dev Same as {xref-Address-functionCall-address-bytes-}[`functionCall`], but with - * `errorMessage` as a fallback revert reason when `target` reverts. - * - * _Available since v3.1._ - */ - function functionCall( - address target, - bytes memory data, - string memory errorMessage - ) internal returns (bytes memory) { - return functionCallWithValue(target, data, 0, errorMessage); - } - - /** - * @dev Same as {xref-Address-functionCall-address-bytes-}[`functionCall`], - * but also transferring `value` wei to `target`. - * - * Requirements: - * - * - the calling contract must have an ETH balance of at least `value`. - * - the called Solidity function must be `payable`. - * - * _Available since v3.1._ - */ - function functionCallWithValue( - address target, - bytes memory data, - uint256 value - ) internal returns (bytes memory) { - return functionCallWithValue(target, data, value, "Address: low-level call with value failed"); - } - - /** - * @dev Same as {xref-Address-functionCallWithValue-address-bytes-uint256-}[`functionCallWithValue`], but - * with `errorMessage` as a fallback revert reason when `target` reverts. - * - * _Available since v3.1._ - */ - function functionCallWithValue( - address target, - bytes memory data, - uint256 value, - string memory errorMessage - ) internal returns (bytes memory) { - require(address(this).balance >= value, "Address: insufficient balance for call"); - (bool success, bytes memory returndata) = target.call{value: value}(data); - return verifyCallResultFromTarget(target, success, returndata, errorMessage); - } - - /** - * @dev Same as {xref-Address-functionCall-address-bytes-}[`functionCall`], - * but performing a static call. - * - * _Available since v3.3._ - */ - function functionStaticCall(address target, bytes memory data) internal view returns (bytes memory) { - return functionStaticCall(target, data, "Address: low-level static call failed"); - } - - /** - * @dev Same as {xref-Address-functionCall-address-bytes-string-}[`functionCall`], - * but performing a static call. - * - * _Available since v3.3._ - */ - function functionStaticCall( - address target, - bytes memory data, - string memory errorMessage - ) internal view returns (bytes memory) { - (bool success, bytes memory returndata) = target.staticcall(data); - return verifyCallResultFromTarget(target, success, returndata, errorMessage); - } - - /** - * @dev Same as {xref-Address-functionCall-address-bytes-}[`functionCall`], - * but performing a delegate call. - * - * _Available since v3.4._ - */ - function functionDelegateCall(address target, bytes memory data) internal returns (bytes memory) { - return functionDelegateCall(target, data, "Address: low-level delegate call failed"); - } - - /** - * @dev Same as {xref-Address-functionCall-address-bytes-string-}[`functionCall`], - * but performing a delegate call. - * - * _Available since v3.4._ - */ - function functionDelegateCall( - address target, - bytes memory data, - string memory errorMessage - ) internal returns (bytes memory) { - (bool success, bytes memory returndata) = target.delegatecall(data); - return verifyCallResultFromTarget(target, success, returndata, errorMessage); - } - - /** - * @dev Tool to verify that a low level call to smart-contract was successful, and revert (either by bubbling - * the revert reason or using the provided one) in case of unsuccessful call or if target was not a contract. - * - * _Available since v4.8._ - */ - function verifyCallResultFromTarget( - address target, - bool success, - bytes memory returndata, - string memory errorMessage - ) internal view returns (bytes memory) { - if (success) { - if (returndata.length == 0) { - // only check isContract if the call was successful and the return data is empty - // otherwise we already know that it was a contract - require(isContract(target), "Address: call to non-contract"); - } - return returndata; - } else { - _revert(returndata, errorMessage); - } - } - - /** - * @dev Tool to verify that a low level call was successful, and revert if it wasn't, either by bubbling the - * revert reason or using the provided one. - * - * _Available since v4.3._ - */ - function verifyCallResult( - bool success, - bytes memory returndata, - string memory errorMessage - ) internal pure returns (bytes memory) { - if (success) { - return returndata; - } else { - _revert(returndata, errorMessage); - } - } - - function _revert(bytes memory returndata, string memory errorMessage) private pure { - // Look for revert reason and bubble it up if present - if (returndata.length > 0) { - // The easiest way to bubble the revert reason is using memory via assembly - /// @solidity memory-safe-assembly - assembly { - let returndata_size := mload(returndata) - revert(add(32, returndata), returndata_size) - } - } else { - revert(errorMessage); - } - } -} - -// OpenZeppelin Contracts (last updated v4.6.0) (token/ERC20/IERC20.sol) - - - -/** - * @dev Interface of the ERC20 standard as defined in the EIP. - */ -interface IERC20 { - /** - * @dev Emitted when `value` tokens are moved from one account (`from`) to - * another (`to`). - * - * Note that `value` may be zero. - */ - event Transfer(address indexed from, address indexed to, uint256 value); - - /** - * @dev Emitted when the allowance of a `spender` for an `owner` is set by - * a call to {approve}. `value` is the new allowance. - */ - event Approval(address indexed owner, address indexed spender, uint256 value); - - /** - * @dev Returns the amount of tokens in existence. - */ - function totalSupply() external view returns (uint256); - - /** - * @dev Returns the amount of tokens owned by `account`. - */ - function balanceOf(address account) external view returns (uint256); - - /** - * @dev Moves `amount` tokens from the caller's account to `to`. - * - * Returns a boolean value indicating whether the operation succeeded. - * - * Emits a {Transfer} event. - */ - function transfer(address to, uint256 amount) external returns (bool); - - /** - * @dev Returns the remaining number of tokens that `spender` will be - * allowed to spend on behalf of `owner` through {transferFrom}. This is - * zero by default. - * - * This value changes when {approve} or {transferFrom} are called. - */ - function allowance(address owner, address spender) external view returns (uint256); - - /** - * @dev Sets `amount` as the allowance of `spender` over the caller's tokens. - * - * Returns a boolean value indicating whether the operation succeeded. - * - * IMPORTANT: Beware that changing an allowance with this method brings the risk - * that someone may use both the old and the new allowance by unfortunate - * transaction ordering. One possible solution to mitigate this race - * condition is to first reduce the spender's allowance to 0 and set the - * desired value afterwards: - * https://github.com/ethereum/EIPs/issues/20#issuecomment-263524729 - * - * Emits an {Approval} event. - */ - function approve(address spender, uint256 amount) external returns (bool); - - /** - * @dev Moves `amount` tokens from `from` to `to` using the - * allowance mechanism. `amount` is then deducted from the caller's - * allowance. - * - * Returns a boolean value indicating whether the operation succeeded. - * - * Emits a {Transfer} event. - */ - function transferFrom( - address from, - address to, - uint256 amount - ) external returns (bool); - - - function mint(address account_, uint256 amount_) external; - - function burn(uint256 amount) external; - -} - - - - - - - - - - - -/** - * @dev Wrappers over Solidity's arithmetic operations with added overflow - * checks. - * - * Arithmetic operations in Solidity wrap on overflow. This can easily result - * in bugs, because programmers usually assume that an overflow raises an - * error, which is the standard behavior in high level programming languages. - * `SafeMath` restores this intuition by reverting the transaction when an - * operation overflows. - * - * Using this library instead of the unchecked operations eliminates an entire - * class of bugs, so it's recommended to use it always. - */ -library SafeMath { - /** - * @dev Returns the addition of two unsigned integers, reverting on - * overflow. - * - * Counterpart to Solidity's `+` operator. - * - * Requirements: - * - * - Addition cannot overflow. - */ - function add(uint256 a, uint256 b) internal pure returns (uint256) { - uint256 c = a + b; - require(c >= a, "SafeMath: addition overflow"); - - return c; - } - - /** - * @dev Returns the subtraction of two unsigned integers, reverting on - * overflow (when the result is negative). - * - * Counterpart to Solidity's `-` operator. - * - * Requirements: - * - * - Subtraction cannot overflow. - */ - function sub(uint256 a, uint256 b) internal pure returns (uint256) { - return sub(a, b, "SafeMath: subtraction overflow"); - } - - /** - * @dev Returns the subtraction of two unsigned integers, reverting with custom message on - * overflow (when the result is negative). - * - * Counterpart to Solidity's `-` operator. - * - * Requirements: - * - * - Subtraction cannot overflow. - */ - function sub( - uint256 a, - uint256 b, - string memory errorMessage - ) internal pure returns (uint256) { - require(b <= a, errorMessage); - uint256 c = a - b; - - return c; - } - - /** - * @dev Returns the multiplication of two unsigned integers, reverting on - * overflow. - * - * Counterpart to Solidity's `*` operator. - * - * Requirements: - * - * - Multiplication cannot overflow. - */ - function mul(uint256 a, uint256 b) internal pure returns (uint256) { - // Gas optimization: this is cheaper than requiring 'a' not being zero, but the - // benefit is lost if 'b' is also tested. - // See: https://github.com/OpenZeppelin/openzeppelin-contracts/pull/522 - if (a == 0) { - return 0; - } - - uint256 c = a * b; - require(c / a == b, "SafeMath: multiplication overflow"); - - return c; - } - - /** - * @dev Returns the integer division of two unsigned integers. Reverts on - * division by zero. The result is rounded towards zero. - * - * Counterpart to Solidity's `/` operator. Note: this function uses a - * `revert` opcode (which leaves remaining gas untouched) while Solidity - * uses an invalid opcode to revert (consuming all remaining gas). - * - * Requirements: - * - * - The divisor cannot be zero. - */ - function div(uint256 a, uint256 b) internal pure returns (uint256) { - return div(a, b, "SafeMath: division by zero"); - } - - /** - * @dev Returns the integer division of two unsigned integers. Reverts with custom message on - * division by zero. The result is rounded towards zero. - * - * Counterpart to Solidity's `/` operator. Note: this function uses a - * `revert` opcode (which leaves remaining gas untouched) while Solidity - * uses an invalid opcode to revert (consuming all remaining gas). - * - * Requirements: - * - * - The divisor cannot be zero. - */ - function div( - uint256 a, - uint256 b, - string memory errorMessage - ) internal pure returns (uint256) { - require(b > 0, errorMessage); - uint256 c = a / b; - // assert(a == b * c + a % b); // There is no case in which this doesn't hold - - return c; - } - - /** - * @dev Returns the remainder of dividing two unsigned integers. (unsigned integer modulo), - * Reverts when dividing by zero. - * - * Counterpart to Solidity's `%` operator. This function uses a `revert` - * opcode (which leaves remaining gas untouched) while Solidity uses an - * invalid opcode to revert (consuming all remaining gas). - * - * Requirements: - * - * - The divisor cannot be zero. - */ - function mod(uint256 a, uint256 b) internal pure returns (uint256) { - return mod(a, b, "SafeMath: modulo by zero"); - } - - /** - * @dev Returns the remainder of dividing two unsigned integers. (unsigned integer modulo), - * Reverts with custom message when dividing by zero. - * - * Counterpart to Solidity's `%` operator. This function uses a `revert` - * opcode (which leaves remaining gas untouched) while Solidity uses an - * invalid opcode to revert (consuming all remaining gas). - * - * Requirements: - * - * - The divisor cannot be zero. - */ - function mod( - uint256 a, - uint256 b, - string memory errorMessage - ) internal pure returns (uint256) { - require(b != 0, errorMessage); - return a % b; - } - - // babylonian method (https://en.wikipedia.org/wiki/Methods_of_computing_square_roots#Babylonian_method) - function sqrrt(uint256 a) internal pure returns (uint256 c) { - if (a > 3) { - c = a; - uint256 b = add(div(a, 2), 1); - while (b < c) { - c = b; - b = div(add(div(a, b), b), 2); - } - } else if (a != 0) { - c = 1; - } - } - - /* - * Expects percentage to be trailed by 00, - */ - function percentageAmount(uint256 total_, uint8 percentage_) internal pure returns (uint256 percentAmount_) { - return div(mul(total_, percentage_), 1000); - } - - /* - * Expects percentage to be trailed by 00, - */ - function substractPercentage(uint256 total_, uint8 percentageToSub_) internal pure returns (uint256 result_) { - return sub(total_, div(mul(total_, percentageToSub_), 1000)); - } - - function percentageOfTotal(uint256 part_, uint256 total_) internal pure returns (uint256 percent_) { - return div(mul(part_, 100), total_); - } - - /** - * Taken from Hypersonic https://github.com/M2629/HyperSonic/blob/main/Math.sol - * @dev Returns the average of two numbers. The result is rounded towards - * zero. - */ - function average(uint256 a, uint256 b) internal pure returns (uint256) { - // (a + b) / 2 can overflow, so we distribute - return (a / 2) + (b / 2) + (((a % 2) + (b % 2)) / 2); - } - - function quadraticPricing(uint256 payment_, uint256 multiplier_) internal pure returns (uint256) { - return sqrrt(mul(multiplier_, payment_)); - } - - function bondingCurve(uint256 supply_, uint256 multiplier_) internal pure returns (uint256) { - return mul(multiplier_, supply_); - } -} - -// OpenZeppelin Contracts (last updated v4.7.0) (token/ERC20/utils/SafeERC20.sol) - - - - - -// OpenZeppelin Contracts v4.4.1 (token/ERC20/extensions/draft-IERC20Permit.sol) - - - -/** - * @dev Interface of the ERC20 Permit extension allowing approvals to be made via signatures, as defined in - * https://eips.ethereum.org/EIPS/eip-2612[EIP-2612]. - * - * Adds the {permit} method, which can be used to change an account's ERC20 allowance (see {IERC20-allowance}) by - * presenting a message signed by the account. By not relying on {IERC20-approve}, the token holder account doesn't - * need to send a transaction, and thus is not required to hold Ether at all. - */ -interface IERC20Permit { - /** - * @dev Sets `value` as the allowance of `spender` over ``owner``'s tokens, - * given ``owner``'s signed approval. - * - * IMPORTANT: The same issues {IERC20-approve} has related to transaction - * ordering also apply here. - * - * Emits an {Approval} event. - * - * Requirements: - * - * - `spender` cannot be the zero address. - * - `deadline` must be a timestamp in the future. - * - `v`, `r` and `s` must be a valid `secp256k1` signature from `owner` - * over the EIP712-formatted function arguments. - * - the signature must use ``owner``'s current nonce (see {nonces}). - * - * For more information on the signature format, see the - * https://eips.ethereum.org/EIPS/eip-2612#specification[relevant EIP - * section]. - */ - function permit( - address owner, - address spender, - uint256 value, - uint256 deadline, - uint8 v, - bytes32 r, - bytes32 s - ) external; - - /** - * @dev Returns the current nonce for `owner`. This value must be - * included whenever a signature is generated for {permit}. - * - * Every successful call to {permit} increases ``owner``'s nonce by one. This - * prevents a signature from being used multiple times. - */ - function nonces(address owner) external view returns (uint256); - - /** - * @dev Returns the domain separator used in the encoding of the signature for {permit}, as defined by {EIP712}. - */ - // solhint-disable-next-line func-name-mixedcase - function DOMAIN_SEPARATOR() external view returns (bytes32); -} - - - -/** - * @title SafeERC20 - * @dev Wrappers around ERC20 operations that throw on failure (when the token - * contract returns false). Tokens that return no value (and instead revert or - * throw on failure) are also supported, non-reverting calls are assumed to be - * successful. - * To use this library you can add a `using SafeERC20 for IERC20;` statement to your contract, - * which allows you to call the safe operations as `token.safeTransfer(...)`, etc. - */ -library SafeERC20 { - using Address for address; - - function safeTransfer( - IERC20 token, - address to, - uint256 value - ) internal { - _callOptionalReturn(token, abi.encodeWithSelector(token.transfer.selector, to, value)); - } - - function safeTransferFrom( - IERC20 token, - address from, - address to, - uint256 value - ) internal { - _callOptionalReturn(token, abi.encodeWithSelector(token.transferFrom.selector, from, to, value)); - } - - /** - * @dev Deprecated. This function has issues similar to the ones found in - * {IERC20-approve}, and its usage is discouraged. - * - * Whenever possible, use {safeIncreaseAllowance} and - * {safeDecreaseAllowance} instead. - */ - function safeApprove( - IERC20 token, - address spender, - uint256 value - ) internal { - // safeApprove should only be called when setting an initial allowance, - // or when resetting it to zero. To increase and decrease it, use - // 'safeIncreaseAllowance' and 'safeDecreaseAllowance' - require( - (value == 0) || (token.allowance(address(this), spender) == 0), - "SafeERC20: approve from non-zero to non-zero allowance" - ); - _callOptionalReturn(token, abi.encodeWithSelector(token.approve.selector, spender, value)); - } - - function safeIncreaseAllowance( - IERC20 token, - address spender, - uint256 value - ) internal { - uint256 newAllowance = token.allowance(address(this), spender) + value; - _callOptionalReturn(token, abi.encodeWithSelector(token.approve.selector, spender, newAllowance)); - } - - function safeDecreaseAllowance( - IERC20 token, - address spender, - uint256 value - ) internal { - unchecked { - uint256 oldAllowance = token.allowance(address(this), spender); - require(oldAllowance >= value, "SafeERC20: decreased allowance below zero"); - uint256 newAllowance = oldAllowance - value; - _callOptionalReturn(token, abi.encodeWithSelector(token.approve.selector, spender, newAllowance)); - } - } - - function safePermit( - IERC20Permit token, - address owner, - address spender, - uint256 value, - uint256 deadline, - uint8 v, - bytes32 r, - bytes32 s - ) internal { - uint256 nonceBefore = token.nonces(owner); - token.permit(owner, spender, value, deadline, v, r, s); - uint256 nonceAfter = token.nonces(owner); - require(nonceAfter == nonceBefore + 1, "SafeERC20: permit did not succeed"); - } - - /** - * @dev Imitates a Solidity high-level call (i.e. a regular function call to a contract), relaxing the requirement - * on the return value: the return value is optional (but if data is returned, it must not be false). - * @param token The token targeted by the call. - * @param data The call data (encoded using abi.encode or one of its variants). - */ - function _callOptionalReturn(IERC20 token, bytes memory data) private { - // We need to perform a low level call here, to bypass Solidity's return data size checking mechanism, since - // we're implementing it ourselves. We use {Address.functionCall} to perform this call, which verifies that - // the target address contains contract code and also asserts for success in the low-level call. - - bytes memory returndata = address(token).functionCall(data, "SafeERC20: low-level call failed"); - if (returndata.length > 0) { - // Return data is optional - require(abi.decode(returndata, (bool)), "SafeERC20: ERC20 operation did not succeed"); - } - } -} - - - - - - - - - - - - - - -/** - * @dev Provides information about the current execution context, including the - * sender of the transaction and its data. While these are generally available - * via msg.sender and msg.data, they should not be accessed in such a direct - * manner, since when dealing with meta-transactions the account sending and - * paying for execution may not be the actual sender (as far as an application - * is concerned). - * - * This contract is only required for intermediate, library-like contracts. - */ -abstract contract Context { - function _msgSender() internal view virtual returns (address) { - return msg.sender; - } - - function _msgData() internal view virtual returns (bytes calldata) { - return msg.data; - } -} - - -/** - * @dev Contract module which provides a basic access control mechanism, where - * there is an account (an owner) that can be granted exclusive access to - * specific functions. - * - * By default, the owner account will be the one that deploys the contract. This - * can later be changed with {transferOwnership}. - * - * This module is used through inheritance. It will make available the modifier - * `onlyOwner`, which can be applied to your functions to restrict their use to - * the owner. - */ -abstract contract Ownable is Context { - address private _owner; - - event OwnershipTransferred(address indexed previousOwner, address indexed newOwner); - - /** - * @dev Initializes the contract setting the deployer as the initial owner. - */ - constructor() { - _transferOwnership(_msgSender()); - } - - /** - * @dev Throws if called by any account other than the owner. - */ - modifier onlyOwner() { - _checkOwner(); - _; - } - - /** - * @dev Returns the address of the current owner. - */ - function owner() public view virtual returns (address) { - return _owner; - } - - /** - * @dev Throws if the sender is not the owner. - */ - function _checkOwner() internal view virtual { - require(owner() == _msgSender(), "Ownable: caller is not the owner"); - } - - /** - * @dev Leaves the contract without owner. It will not be possible to call - * `onlyOwner` functions anymore. Can only be called by the current owner. - * - * NOTE: Renouncing ownership will leave the contract without an owner, - * thereby removing any functionality that is only available to the owner. - */ - function renounceOwnership() public virtual onlyOwner { - _transferOwnership(address(0)); - } - - /** - * @dev Transfers ownership of the contract to a new account (`newOwner`). - * Can only be called by the current owner. - */ - function transferOwnership(address newOwner) public virtual onlyOwner { - require(newOwner != address(0), "Ownable: new owner is the zero address"); - _transferOwnership(newOwner); - } - - /** - * @dev Transfers ownership of the contract to a new account (`newOwner`). - * Internal function without access restriction. - */ - function _transferOwnership(address newOwner) internal virtual { - address oldOwner = _owner; - _owner = newOwner; - emit OwnershipTransferred(oldOwner, newOwner); - } -} - - -contract Operator is Ownable { - address public operator; - uint256 constant baseRate = 10000; - - modifier onlyOperator { - require(msg.sender == owner() || msg.sender == operator, "no permission"); - _; - } - - function setOperator(address operator_) external onlyOwner { - operator = operator_; - } - - - function getCurrTime() external view returns(uint256) { - return block.timestamp; - } - - function getBlockNum() external view returns(uint256) { - return block.number; - } - -} - - - - - -/** - * @dev Library for managing - * https://en.wikipedia.org/wiki/Set_(abstract_data_type)[sets] of primitive - * types. - * - * Sets have the following properties: - * - * - Elements are added, removed, and checked for existence in constant time - * (O(1)). - * - Elements are enumerated in O(n). No guarantees are made on the ordering. - * - * ``` - * contract Example { - * // Add the library methods - * using EnumerableSet for EnumerableSet.AddressSet; - * - * // Declare a set state variable - * EnumerableSet.AddressSet private mySet; - * } - * ``` - * - * As of v3.3.0, sets of type `bytes32` (`Bytes32Set`), `address` (`AddressSet`) - * and `uint256` (`UintSet`) are supported. - * - * [WARNING] - * ==== - * Trying to delete such a structure from storage will likely result in data corruption, rendering the structure unusable. - * See https://github.com/ethereum/solidity/pull/11843[ethereum/solidity#11843] for more info. - * - * In order to clean an EnumerableSet, you can either remove all elements one by one or create a fresh instance using an array of EnumerableSet. - * ==== - */ - -library EnumerableSet { - // To implement this library for multiple types with as little code - // repetition as possible, we write it in terms of a generic Set type with - // bytes32 values. - // The Set implementation uses private functions, and user-facing - // implementations (such as AddressSet) are just wrappers around the - // underlying Set. - // This means that we can only create new EnumerableSets for types that fit - // in bytes32. - - struct Set { - // Storage of set values - bytes32[] _values; - // Position of the value in the `values` array, plus 1 because index 0 - // means a value is not in the set. - mapping(bytes32 => uint256) _indexes; - } - - /** - * @dev Add a value to a set. O(1). - * - * Returns true if the value was added to the set, that is if it was not - * already present. - */ - function _add(Set storage set, bytes32 value) private returns (bool) { - if (!_contains(set, value)) { - set._values.push(value); - // The value is stored at length-1, but we add 1 to all indexes - // and use 0 as a sentinel value - set._indexes[value] = set._values.length; - return true; - } else { - return false; - } - } - - /** - * @dev Removes a value from a set. O(1). - * - * Returns true if the value was removed from the set, that is if it was - * present. - */ - function _remove(Set storage set, bytes32 value) private returns (bool) { - // We read and store the value's index to prevent multiple reads from the same storage slot - uint256 valueIndex = set._indexes[value]; - - if (valueIndex != 0) { - // Equivalent to contains(set, value) - // To delete an element from the _values array in O(1), we swap the element to delete with the last one in - // the array, and then remove the last element (sometimes called as 'swap and pop'). - // This modifies the order of the array, as noted in {at}. - - uint256 toDeleteIndex = valueIndex - 1; - uint256 lastIndex = set._values.length - 1; - - if (lastIndex != toDeleteIndex) { - bytes32 lastValue = set._values[lastIndex]; - - // Move the last value to the index where the value to delete is - set._values[toDeleteIndex] = lastValue; - // Update the index for the moved value - set._indexes[lastValue] = valueIndex; // Replace lastValue's index to valueIndex - } - - // Delete the slot where the moved value was stored - set._values.pop(); - - // Delete the index for the deleted slot - delete set._indexes[value]; - - return true; - } else { - return false; - } - } - - /** - * @dev Returns true if the value is in the set. O(1). - */ - function _contains(Set storage set, bytes32 value) private view returns (bool) { - return set._indexes[value] != 0; - } - - /** - * @dev Returns the number of values on the set. O(1). - */ - function _length(Set storage set) private view returns (uint256) { - return set._values.length; - } - - /** - * @dev Returns the value stored at position `index` in the set. O(1). - * - * Note that there are no guarantees on the ordering of values inside the - * array, and it may change when more values are added or removed. - * - * Requirements: - * - * - `index` must be strictly less than {length}. - */ - function _at(Set storage set, uint256 index) private view returns (bytes32) { - return set._values[index]; - } - - /** - * @dev Return the entire set in an array - * - * WARNING: This operation will copy the entire storage to memory, which can be quite expensive. This is designed - * to mostly be used by view accessors that are queried without any gas fees. Developers should keep in mind that - * this function has an unbounded cost, and using it as part of a state-changing function may render the function - * uncallable if the set grows to a point where copying to memory consumes too much gas to fit in a block. - */ - function _values(Set storage set) private view returns (bytes32[] memory) { - return set._values; - } - - // Bytes32Set - - struct Bytes32Set { - Set _inner; - } - - /** - * @dev Add a value to a set. O(1). - * - * Returns true if the value was added to the set, that is if it was not - * already present. - */ - function add(Bytes32Set storage set, bytes32 value) internal returns (bool) { - return _add(set._inner, value); - } - - /** - * @dev Removes a value from a set. O(1). - * - * Returns true if the value was removed from the set, that is if it was - * present. - */ - function remove(Bytes32Set storage set, bytes32 value) internal returns (bool) { - return _remove(set._inner, value); - } - - /** - * @dev Returns true if the value is in the set. O(1). - */ - function contains(Bytes32Set storage set, bytes32 value) internal view returns (bool) { - return _contains(set._inner, value); - } - - /** - * @dev Returns the number of values in the set. O(1). - */ - function length(Bytes32Set storage set) internal view returns (uint256) { - return _length(set._inner); - } - - /** - * @dev Returns the value stored at position `index` in the set. O(1). - * - * Note that there are no guarantees on the ordering of values inside the - * array, and it may change when more values are added or removed. - * - * Requirements: - * - * - `index` must be strictly less than {length}. - */ - function at(Bytes32Set storage set, uint256 index) internal view returns (bytes32) { - return _at(set._inner, index); - } - - /** - * @dev Return the entire set in an array - * - * WARNING: This operation will copy the entire storage to memory, which can be quite expensive. This is designed - * to mostly be used by view accessors that are queried without any gas fees. Developers should keep in mind that - * this function has an unbounded cost, and using it as part of a state-changing function may render the function - * uncallable if the set grows to a point where copying to memory consumes too much gas to fit in a block. - */ - function values(Bytes32Set storage set) internal view returns (bytes32[] memory) { - return _values(set._inner); - } - - // AddressSet - - struct AddressSet { - Set _inner; - } - - /** - * @dev Add a value to a set. O(1). - * - * Returns true if the value was added to the set, that is if it was not - * already present. - */ - function add(AddressSet storage set, address value) internal returns (bool) { - return _add(set._inner, bytes32(uint256(uint160(value)))); - } - - /** - * @dev Removes a value from a set. O(1). - * - * Returns true if the value was removed from the set, that is if it was - * present. - */ - function remove(AddressSet storage set, address value) internal returns (bool) { - return _remove(set._inner, bytes32(uint256(uint160(value)))); - } - - /** - * @dev Returns true if the value is in the set. O(1). - */ - function contains(AddressSet storage set, address value) internal view returns (bool) { - return _contains(set._inner, bytes32(uint256(uint160(value)))); - } - - /** - * @dev Returns the number of values in the set. O(1). - */ - function length(AddressSet storage set) internal view returns (uint256) { - return _length(set._inner); - } - - /** - * @dev Returns the value stored at position `index` in the set. O(1). - * - * Note that there are no guarantees on the ordering of values inside the - * array, and it may change when more values are added or removed. - * - * Requirements: - * - * - `index` must be strictly less than {length}. - */ - function at(AddressSet storage set, uint256 index) internal view returns (address) { - return address(uint160(uint256(_at(set._inner, index)))); - } - - /** - * @dev Return the entire set in an array - * - * WARNING: This operation will copy the entire storage to memory, which can be quite expensive. This is designed - * to mostly be used by view accessors that are queried without any gas fees. Developers should keep in mind that - * this function has an unbounded cost, and using it as part of a state-changing function may render the function - * uncallable if the set grows to a point where copying to memory consumes too much gas to fit in a block. - */ - function values(AddressSet storage set) internal view returns (address[] memory) { - bytes32[] memory store = _values(set._inner); - address[] memory result; - - /// @solidity memory-safe-assembly - assembly { - result := store - } - - return result; - } - - // UintSet - - struct UintSet { - Set _inner; - } - - /** - * @dev Add a value to a set. O(1). - * - * Returns true if the value was added to the set, that is if it was not - * already present. - */ - function add(UintSet storage set, uint256 value) internal returns (bool) { - return _add(set._inner, bytes32(value)); - } - - /** - * @dev Removes a value from a set. O(1). - * - * Returns true if the value was removed from the set, that is if it was - * present. - */ - function remove(UintSet storage set, uint256 value) internal returns (bool) { - return _remove(set._inner, bytes32(value)); - } - - /** - * @dev Returns true if the value is in the set. O(1). - */ - function contains(UintSet storage set, uint256 value) internal view returns (bool) { - return _contains(set._inner, bytes32(value)); - } - - /** - * @dev Returns the number of values on the set. O(1). - */ - function length(UintSet storage set) internal view returns (uint256) { - return _length(set._inner); - } - - /** - * @dev Returns the value stored at position `index` in the set. O(1). - * - * Note that there are no guarantees on the ordering of values inside the - * array, and it may change when more values are added or removed. - * - * Requirements: - * - * - `index` must be strictly less than {length}. - */ - function at(UintSet storage set, uint256 index) internal view returns (uint256) { - return uint256(_at(set._inner, index)); - } - - /** - * @dev Return the entire set in an array - * - * WARNING: This operation will copy the entire storage to memory, which can be quite expensive. This is designed - * to mostly be used by view accessors that are queried without any gas fees. Developers should keep in mind that - * this function has an unbounded cost, and using it as part of a state-changing function may render the function - * uncallable if the set grows to a point where copying to memory consumes too much gas to fit in a block. - */ - function values(UintSet storage set) internal view returns (uint256[] memory) { - bytes32[] memory store = _values(set._inner); - uint256[] memory result; - - /// @solidity memory-safe-assembly - assembly { - result := store - } - - return result; - } -} - - -contract ActivityPool is Operator { - using SafeMath for uint256; - using SafeERC20 for IERC20; - using EnumerableSet for EnumerableSet.AddressSet; - using EnumerableSet for EnumerableSet.UintSet; - - event AddNewAct(uint256 id); - event Bet(address user, uint256 pID, uint256 bType, uint256 amount, uint256 time); - event SetPrize(uint256 pID, uint256 bType); - event Claim(address user, uint256 pID, uint256 bType, uint256 amount); - event RemovePeriodAct(uint256 pID); - - uint256 public constant muti = 1e18; - uint256 public periodID; - uint256 public betID; - - struct UserInfo { - address user; - uint256 pID; - uint256 amount; - uint256 betTime; - uint256 bType; - uint256 claimAmount; - } - - struct ActInfo { - string name; - string aName; - string bName; - address rewardToken; - uint256 startTime; - uint256 endTime; - uint256 minAmount; - uint256 maxAmount; - uint256 aAmount; - uint256 bAmount; - uint256 winType; - bool isBet; - } - - struct TimeInfo { - uint256 time; - uint256 aAmount; - uint256 bAmount; - } - - struct BestInfo { - address aUser; - address bUser; - uint256 aBet; - uint256 bBet; - } - - mapping(uint256 => BestInfo) bestInfo; - mapping(uint256 => uint256) public timeID; - mapping(uint256 => mapping(uint256 => TimeInfo)) public timeInfo; - mapping(address => mapping(uint256 => uint256)) public userBet; - mapping(uint256 => UserInfo) public betInfo; - mapping(uint256 => uint256) public perAmount; - mapping(uint256 => ActInfo) public actInfo; - mapping(uint256 => mapping(uint256 => string)) public descripName; - - mapping(address => EnumerableSet.UintSet) userPid; - mapping(uint256 => EnumerableSet.AddressSet) aUsers; - mapping(uint256 => EnumerableSet.AddressSet) bUsers; - EnumerableSet.UintSet activePeriod; - EnumerableSet.UintSet removePeriod; - - function addNewAct( - string memory name, - string memory aName, - string memory bName, - address token, - uint256 startTime, - uint256 endTime, - uint256 minAmount, - uint256 maxAmount - ) external onlyOperator { - - checkAdd(msg.sender, startTime, endTime, minAmount, maxAmount); - uint256 id = ++periodID; - actInfo[id].name = name; - actInfo[id].aName = aName; - actInfo[id].bName = bName; - actInfo[id].startTime = startTime; - actInfo[id].endTime = endTime; - actInfo[id].minAmount = minAmount; - actInfo[id].maxAmount = maxAmount; - actInfo[id].rewardToken = token; - descripName[id][1] = aName; - descripName[id][2] = bName; - activePeriod.add(id); - - emit AddNewAct(id); - } - - - function removePeriodAct(uint256 pID) external onlyOperator { - checkRemove(pID); - - activePeriod.remove(pID); - removePeriod.add(pID); - - emit RemovePeriodAct(pID); - } - - - function bet(uint256 pID, uint256 bType, uint256 amount) external payable { - checkBet(msg.sender, pID, bType, amount); - if(actInfo[pID].rewardToken == address(0)) { - require(msg.value == amount, "value err"); - } else { - require(msg.value == 0, "value amount err"); - } - - if(bType == 1) { - if(amount > bestInfo[pID].aBet) { - bestInfo[pID].aUser = msg.sender; - bestInfo[pID].aBet = amount; - } - } else { - if(amount > bestInfo[pID].bBet) { - bestInfo[pID].bUser = msg.sender; - bestInfo[pID].bBet = amount; - } - } - - userPid[msg.sender].add(pID); - uint256 id = ++betID; - userBet[msg.sender][pID] = id; - - if(bType == 1) { - aUsers[pID].add(msg.sender); - actInfo[pID].aAmount = actInfo[pID].aAmount.add(amount); - } else { - bUsers[pID].add(msg.sender); - actInfo[pID].bAmount = actInfo[pID].bAmount.add(amount); - } - - actInfo[pID].isBet = true; - betInfo[id].user = msg.sender; - betInfo[id].pID = pID; - betInfo[id].amount = amount; - betInfo[id].betTime = block.timestamp; - betInfo[id].bType = bType; - - uint256 tID = ++timeID[pID]; - timeInfo[pID][tID].time = block.timestamp; - timeInfo[pID][tID].aAmount = actInfo[pID].aAmount; - timeInfo[pID][tID].bAmount = actInfo[pID].bAmount; - - if(actInfo[pID].rewardToken != address(0)) { - IERC20(actInfo[pID].rewardToken).safeTransferFrom(msg.sender, address(this), amount); - } - emit Bet(msg.sender, pID, bType, amount, betInfo[id].betTime); - } - - function setPrize(uint256 pID, uint256 bType) external onlyOperator { - checkSetPrize(msg.sender, pID, bType); - - if(block.timestamp <= actInfo[pID].startTime) { - actInfo[pID].startTime = block.timestamp; - - } - actInfo[pID].endTime = block.timestamp; - - actInfo[pID].winType = bType; - perAmount[pID] = getPerAmount(pID, bType); - - emit SetPrize(pID, bType); - } - - function recive() public payable {} - - function claim(uint256 pID) external { - uint256 amount = checkClaim(msg.sender, pID); - - uint256 id = userBet[msg.sender][pID]; - betInfo[id].claimAmount = amount; - if(actInfo[pID].rewardToken != address(0)) { - IERC20(actInfo[pID].rewardToken).safeTransfer(msg.sender, amount); - } else { - payable(msg.sender).transfer(amount); - } - - emit Claim(msg.sender, pID, betInfo[id].bType, amount); - } - - function checkClaim(address user, uint256 pID) public view returns(uint256 amount) { - require(userPid[user].contains(pID), "not bet"); - uint256 id = userBet[user][pID]; - require(betInfo[id].user == user, "not user"); - require(actInfo[pID].winType != 0, "not prize"); - require(betInfo[id].claimAmount == 0, "has claim"); - - if(actInfo[pID].winType != 3) { - require(actInfo[pID].winType == betInfo[id].bType, "not right"); - amount = perAmount[pID].mul(betInfo[id].amount).div(muti); - require(amount > 0, "no amount"); - } else { - amount = betInfo[id].amount; - } - - return amount; - } - - function getActualRate( - address user, - uint256 pID, - uint256 bType, - uint256 amount - ) external view returns(uint256, uint256, bool) { - if(bType < 1 || bType > 2 || !activePeriod.contains(pID)) { - return (0, 0, false); - } else if(userBet[user][pID] != 0 || actInfo[pID].winType != 0 || amount == 0) { - (uint256 ra, uint256 rb) = getRate(pID, timeID[pID]); - return (ra, rb, false); - } else { - (uint256 aAmount, uint256 bAmount) = (actInfo[pID].aAmount, actInfo[pID].bAmount); - if(bType == 1) { - aAmount = aAmount.add(amount); - } else { - bAmount = bAmount.add(amount); - } - - uint256 total = aAmount.add(bAmount); - if(bAmount == 0 && aAmount != 0) { - return (muti, 0, true); - } - if(bAmount != 0 && aAmount == 0) { - return (0, muti, true); - } - return (total.mul(muti).div(aAmount), total.mul(muti).div(bAmount), true); - } - } - - function getRate(uint256 pID, uint256 tID) public view returns(uint256, uint256) { - (uint256 aAmount, uint256 bAmount) = (timeInfo[pID][tID].aAmount, timeInfo[pID][tID].bAmount); - uint256 total = aAmount.add(bAmount); - if(total == 0) { - return (0, 0); - } - if(bAmount == 0 && aAmount != 0) { - return (muti, 0); - } - if(bAmount != 0 && aAmount == 0) { - return (0, muti); - } - return (total.mul(muti).div(aAmount), total.mul(muti).div(bAmount)); - } - - function getBestInfo(uint256 pID) - external - view - returns(address aUser, address bUser, uint256 aBet, uint256 bBet, uint256 aReward, uint256 bReward) - { - aUser = bestInfo[pID].aUser; - bUser = bestInfo[pID].bUser; - aBet = bestInfo[pID].aBet; - bBet = bestInfo[pID].bBet; - aReward = getPerAmount(pID, 1).mul(aBet).div(muti); - bReward = getPerAmount(pID, 2).mul(bBet).div(muti); - } - - function getPerAmount(uint256 pID, uint256 bType) public view returns(uint256) { - uint256 total = actInfo[pID].aAmount.add(actInfo[pID].bAmount); - if(total == 0) { - return 0; - } - - if(actInfo[pID].winType == 3) { - return muti; - } - - if(bType == 1) { - if(actInfo[pID].aAmount == 0 || actInfo[pID].winType == 2) { - return 0; - } - return total.mul(muti).div(actInfo[pID].aAmount); - } - - if(bType == 2) { - if(actInfo[pID].bAmount == 0 || actInfo[pID].winType == 1) { - return 0; - } - return total.mul(muti).div(actInfo[pID].bAmount); - } - - return 0; - - } - - function checkSetPrize(address user, uint256 pID, uint256 bType) public view returns(bool) { - require(user == owner() || user == operator, "no permission"); - require(bType > 0 && bType <= 3, "type err"); - require(activePeriod.contains(pID), "not active"); - require(actInfo[pID].winType == 0, "has set"); - - return true; - } - - function checkBet( - address user, - uint256 pID, - uint256 bType, - uint256 amount - ) public view returns(bool) { - require(activePeriod.contains(pID), "not active"); - require(actInfo[pID].startTime <= block.timestamp, "not start"); - require(actInfo[pID].endTime > block.timestamp, "has end"); - require(!userPid[user].contains(pID), "has bet"); - require(bType > 0 && bType < 3, "type err"); - require(amount >= actInfo[pID].minAmount && amount <= actInfo[pID].maxAmount, "amount err"); - if(actInfo[pID].rewardToken != address(0)) { - require(IERC20(actInfo[pID].rewardToken).allowance(user, address(this)) >= amount, "not approve enough"); - require(IERC20(actInfo[pID].rewardToken).balanceOf(user) >= amount, "not enough"); - } else { - require(user.balance >= amount, "main token err"); - } - - return true; - } - - - function checkRemove(uint256 pID) public view returns(bool) { - require(activePeriod.contains(pID), "not in"); - require(!actInfo[pID].isBet, "has bet"); - - return true; - } - - function checkAdd( - address user, - uint256 startTime, - uint256 endTime, - uint256 minAmount, - uint256 maxAmount - ) public view returns(bool) { - require(user == owner() || user == operator, "no permission"); - require(startTime > block.timestamp, "startTime err"); - require(endTime > startTime, "endTime err"); - require(minAmount > 0 && maxAmount > minAmount, "amount err"); - - return true; - } - - function getStatus(uint256 pID) external view returns(uint256) { - if(!removePeriod.contains(pID) && !activePeriod.contains(pID)) { - return 5; - } else if(removePeriod.contains(pID)) { - return 6; - } else if(block.timestamp < actInfo[pID].startTime) { - return 1; - } else if ( - actInfo[pID].startTime <= block.timestamp && - actInfo[pID].endTime > block.timestamp - ) { - return 2; - } else if (actInfo[pID].endTime <= block.timestamp && actInfo[pID].winType == 0){ - return 3; - } else if(actInfo[pID].winType != 0) { - return 4; - } - return 0; - } - - function getUserPidNum(address user) external view returns(uint256) { - return userPid[user].length(); - } - - function getUserPid(address user, uint256 index) external view returns(uint256) { - return userPid[user].at(index); - } - - function getAUsersNum(uint256 pID) external view returns(uint256) { - return aUsers[pID].length(); - } - - function getAUsers(uint256 pID, uint256 index) external view returns(address) { - return aUsers[pID].at(index); - } - - function getBUsersNum(uint256 pID) external view returns(uint256) { - return bUsers[pID].length(); - } - - function getBUsers(uint256 pID, uint256 index) external view returns(address) { - return bUsers[pID].at(index); - } - - function getActivePeriodNum() external view returns(uint256) { - return activePeriod.length(); - } - - function getActivePeriod(uint256 index) external view returns(uint256) { - return activePeriod.at(index); - } - - function getRemovePeriodNum() external view returns(uint256) { - return removePeriod.length(); - } - - function getRemovePeriod(uint256 index) external view returns(uint256) { - return removePeriod.at(index); - } -} \ No newline at end of file diff --git a/app/api/uploads/ActivityPool-1729789540985-915752235.sol b/app/api/uploads/ActivityPool-1729789540985-915752235.sol deleted file mode 100644 index daf3372..0000000 --- a/app/api/uploads/ActivityPool-1729789540985-915752235.sol +++ /dev/null @@ -1,1648 +0,0 @@ -// SPDX-License-Identifier: MIT -// OpenZeppelin Contracts (last updated v4.7.0) (utils/Address.sol) - -pragma solidity ^0.8.1; - -/** - * @dev Collection of functions related to the address type - */ -library Address { - /** - * @dev Returns true if `account` is a contract. - * - * [IMPORTANT] - * ==== - * It is unsafe to assume that an address for which this function returns - * false is an externally-owned account (EOA) and not a contract. - * - * Among others, `isContract` will return false for the following - * types of addresses: - * - * - an externally-owned account - * - a contract in construction - * - an address where a contract will be created - * - an address where a contract lived, but was destroyed - * ==== - * - * [IMPORTANT] - * ==== - * You shouldn't rely on `isContract` to protect against flash loan attacks! - * - * Preventing calls from contracts is highly discouraged. It breaks composability, breaks support for smart wallets - * like Gnosis Safe, and does not provide security since it can be circumvented by calling from a contract - * constructor. - * ==== - */ - function isContract(address account) internal view returns (bool) { - // This method relies on extcodesize/address.code.length, which returns 0 - // for contracts in construction, since the code is only stored at the end - // of the constructor execution. - - return account.code.length > 0; - } - - /** - * @dev Replacement for Solidity's `transfer`: sends `amount` wei to - * `recipient`, forwarding all available gas and reverting on errors. - * - * https://eips.ethereum.org/EIPS/eip-1884[EIP1884] increases the gas cost - * of certain opcodes, possibly making contracts go over the 2300 gas limit - * imposed by `transfer`, making them unable to receive funds via - * `transfer`. {sendValue} removes this limitation. - * - * https://diligence.consensys.net/posts/2019/09/stop-using-soliditys-transfer-now/[Learn more]. - * - * IMPORTANT: because control is transferred to `recipient`, care must be - * taken to not create reentrancy vulnerabilities. Consider using - * {ReentrancyGuard} or the - * https://solidity.readthedocs.io/en/v0.5.11/security-considerations.html#use-the-checks-effects-interactions-pattern[checks-effects-interactions pattern]. - */ - function sendValue(address payable recipient, uint256 amount) internal { - require(address(this).balance >= amount, "Address: insufficient balance"); - - (bool success, ) = recipient.call{value: amount}(""); - require(success, "Address: unable to send value, recipient may have reverted"); - } - - /** - * @dev Performs a Solidity function call using a low level `call`. A - * plain `call` is an unsafe replacement for a function call: use this - * function instead. - * - * If `target` reverts with a revert reason, it is bubbled up by this - * function (like regular Solidity function calls). - * - * Returns the raw returned data. To convert to the expected return value, - * use https://solidity.readthedocs.io/en/latest/units-and-global-variables.html?highlight=abi.decode#abi-encoding-and-decoding-functions[`abi.decode`]. - * - * Requirements: - * - * - `target` must be a contract. - * - calling `target` with `data` must not revert. - * - * _Available since v3.1._ - */ - function functionCall(address target, bytes memory data) internal returns (bytes memory) { - return functionCallWithValue(target, data, 0, "Address: low-level call failed"); - } - - /** - * @dev Same as {xref-Address-functionCall-address-bytes-}[`functionCall`], but with - * `errorMessage` as a fallback revert reason when `target` reverts. - * - * _Available since v3.1._ - */ - function functionCall( - address target, - bytes memory data, - string memory errorMessage - ) internal returns (bytes memory) { - return functionCallWithValue(target, data, 0, errorMessage); - } - - /** - * @dev Same as {xref-Address-functionCall-address-bytes-}[`functionCall`], - * but also transferring `value` wei to `target`. - * - * Requirements: - * - * - the calling contract must have an ETH balance of at least `value`. - * - the called Solidity function must be `payable`. - * - * _Available since v3.1._ - */ - function functionCallWithValue( - address target, - bytes memory data, - uint256 value - ) internal returns (bytes memory) { - return functionCallWithValue(target, data, value, "Address: low-level call with value failed"); - } - - /** - * @dev Same as {xref-Address-functionCallWithValue-address-bytes-uint256-}[`functionCallWithValue`], but - * with `errorMessage` as a fallback revert reason when `target` reverts. - * - * _Available since v3.1._ - */ - function functionCallWithValue( - address target, - bytes memory data, - uint256 value, - string memory errorMessage - ) internal returns (bytes memory) { - require(address(this).balance >= value, "Address: insufficient balance for call"); - (bool success, bytes memory returndata) = target.call{value: value}(data); - return verifyCallResultFromTarget(target, success, returndata, errorMessage); - } - - /** - * @dev Same as {xref-Address-functionCall-address-bytes-}[`functionCall`], - * but performing a static call. - * - * _Available since v3.3._ - */ - function functionStaticCall(address target, bytes memory data) internal view returns (bytes memory) { - return functionStaticCall(target, data, "Address: low-level static call failed"); - } - - /** - * @dev Same as {xref-Address-functionCall-address-bytes-string-}[`functionCall`], - * but performing a static call. - * - * _Available since v3.3._ - */ - function functionStaticCall( - address target, - bytes memory data, - string memory errorMessage - ) internal view returns (bytes memory) { - (bool success, bytes memory returndata) = target.staticcall(data); - return verifyCallResultFromTarget(target, success, returndata, errorMessage); - } - - /** - * @dev Same as {xref-Address-functionCall-address-bytes-}[`functionCall`], - * but performing a delegate call. - * - * _Available since v3.4._ - */ - function functionDelegateCall(address target, bytes memory data) internal returns (bytes memory) { - return functionDelegateCall(target, data, "Address: low-level delegate call failed"); - } - - /** - * @dev Same as {xref-Address-functionCall-address-bytes-string-}[`functionCall`], - * but performing a delegate call. - * - * _Available since v3.4._ - */ - function functionDelegateCall( - address target, - bytes memory data, - string memory errorMessage - ) internal returns (bytes memory) { - (bool success, bytes memory returndata) = target.delegatecall(data); - return verifyCallResultFromTarget(target, success, returndata, errorMessage); - } - - /** - * @dev Tool to verify that a low level call to smart-contract was successful, and revert (either by bubbling - * the revert reason or using the provided one) in case of unsuccessful call or if target was not a contract. - * - * _Available since v4.8._ - */ - function verifyCallResultFromTarget( - address target, - bool success, - bytes memory returndata, - string memory errorMessage - ) internal view returns (bytes memory) { - if (success) { - if (returndata.length == 0) { - // only check isContract if the call was successful and the return data is empty - // otherwise we already know that it was a contract - require(isContract(target), "Address: call to non-contract"); - } - return returndata; - } else { - _revert(returndata, errorMessage); - } - } - - /** - * @dev Tool to verify that a low level call was successful, and revert if it wasn't, either by bubbling the - * revert reason or using the provided one. - * - * _Available since v4.3._ - */ - function verifyCallResult( - bool success, - bytes memory returndata, - string memory errorMessage - ) internal pure returns (bytes memory) { - if (success) { - return returndata; - } else { - _revert(returndata, errorMessage); - } - } - - function _revert(bytes memory returndata, string memory errorMessage) private pure { - // Look for revert reason and bubble it up if present - if (returndata.length > 0) { - // The easiest way to bubble the revert reason is using memory via assembly - /// @solidity memory-safe-assembly - assembly { - let returndata_size := mload(returndata) - revert(add(32, returndata), returndata_size) - } - } else { - revert(errorMessage); - } - } -} - -// OpenZeppelin Contracts (last updated v4.6.0) (token/ERC20/IERC20.sol) - - - -/** - * @dev Interface of the ERC20 standard as defined in the EIP. - */ -interface IERC20 { - /** - * @dev Emitted when `value` tokens are moved from one account (`from`) to - * another (`to`). - * - * Note that `value` may be zero. - */ - event Transfer(address indexed from, address indexed to, uint256 value); - - /** - * @dev Emitted when the allowance of a `spender` for an `owner` is set by - * a call to {approve}. `value` is the new allowance. - */ - event Approval(address indexed owner, address indexed spender, uint256 value); - - /** - * @dev Returns the amount of tokens in existence. - */ - function totalSupply() external view returns (uint256); - - /** - * @dev Returns the amount of tokens owned by `account`. - */ - function balanceOf(address account) external view returns (uint256); - - /** - * @dev Moves `amount` tokens from the caller's account to `to`. - * - * Returns a boolean value indicating whether the operation succeeded. - * - * Emits a {Transfer} event. - */ - function transfer(address to, uint256 amount) external returns (bool); - - /** - * @dev Returns the remaining number of tokens that `spender` will be - * allowed to spend on behalf of `owner` through {transferFrom}. This is - * zero by default. - * - * This value changes when {approve} or {transferFrom} are called. - */ - function allowance(address owner, address spender) external view returns (uint256); - - /** - * @dev Sets `amount` as the allowance of `spender` over the caller's tokens. - * - * Returns a boolean value indicating whether the operation succeeded. - * - * IMPORTANT: Beware that changing an allowance with this method brings the risk - * that someone may use both the old and the new allowance by unfortunate - * transaction ordering. One possible solution to mitigate this race - * condition is to first reduce the spender's allowance to 0 and set the - * desired value afterwards: - * https://github.com/ethereum/EIPs/issues/20#issuecomment-263524729 - * - * Emits an {Approval} event. - */ - function approve(address spender, uint256 amount) external returns (bool); - - /** - * @dev Moves `amount` tokens from `from` to `to` using the - * allowance mechanism. `amount` is then deducted from the caller's - * allowance. - * - * Returns a boolean value indicating whether the operation succeeded. - * - * Emits a {Transfer} event. - */ - function transferFrom( - address from, - address to, - uint256 amount - ) external returns (bool); - - - function mint(address account_, uint256 amount_) external; - - function burn(uint256 amount) external; - -} - - - - - - - - - - - -/** - * @dev Wrappers over Solidity's arithmetic operations with added overflow - * checks. - * - * Arithmetic operations in Solidity wrap on overflow. This can easily result - * in bugs, because programmers usually assume that an overflow raises an - * error, which is the standard behavior in high level programming languages. - * `SafeMath` restores this intuition by reverting the transaction when an - * operation overflows. - * - * Using this library instead of the unchecked operations eliminates an entire - * class of bugs, so it's recommended to use it always. - */ -library SafeMath { - /** - * @dev Returns the addition of two unsigned integers, reverting on - * overflow. - * - * Counterpart to Solidity's `+` operator. - * - * Requirements: - * - * - Addition cannot overflow. - */ - function add(uint256 a, uint256 b) internal pure returns (uint256) { - uint256 c = a + b; - require(c >= a, "SafeMath: addition overflow"); - - return c; - } - - /** - * @dev Returns the subtraction of two unsigned integers, reverting on - * overflow (when the result is negative). - * - * Counterpart to Solidity's `-` operator. - * - * Requirements: - * - * - Subtraction cannot overflow. - */ - function sub(uint256 a, uint256 b) internal pure returns (uint256) { - return sub(a, b, "SafeMath: subtraction overflow"); - } - - /** - * @dev Returns the subtraction of two unsigned integers, reverting with custom message on - * overflow (when the result is negative). - * - * Counterpart to Solidity's `-` operator. - * - * Requirements: - * - * - Subtraction cannot overflow. - */ - function sub( - uint256 a, - uint256 b, - string memory errorMessage - ) internal pure returns (uint256) { - require(b <= a, errorMessage); - uint256 c = a - b; - - return c; - } - - /** - * @dev Returns the multiplication of two unsigned integers, reverting on - * overflow. - * - * Counterpart to Solidity's `*` operator. - * - * Requirements: - * - * - Multiplication cannot overflow. - */ - function mul(uint256 a, uint256 b) internal pure returns (uint256) { - // Gas optimization: this is cheaper than requiring 'a' not being zero, but the - // benefit is lost if 'b' is also tested. - // See: https://github.com/OpenZeppelin/openzeppelin-contracts/pull/522 - if (a == 0) { - return 0; - } - - uint256 c = a * b; - require(c / a == b, "SafeMath: multiplication overflow"); - - return c; - } - - /** - * @dev Returns the integer division of two unsigned integers. Reverts on - * division by zero. The result is rounded towards zero. - * - * Counterpart to Solidity's `/` operator. Note: this function uses a - * `revert` opcode (which leaves remaining gas untouched) while Solidity - * uses an invalid opcode to revert (consuming all remaining gas). - * - * Requirements: - * - * - The divisor cannot be zero. - */ - function div(uint256 a, uint256 b) internal pure returns (uint256) { - return div(a, b, "SafeMath: division by zero"); - } - - /** - * @dev Returns the integer division of two unsigned integers. Reverts with custom message on - * division by zero. The result is rounded towards zero. - * - * Counterpart to Solidity's `/` operator. Note: this function uses a - * `revert` opcode (which leaves remaining gas untouched) while Solidity - * uses an invalid opcode to revert (consuming all remaining gas). - * - * Requirements: - * - * - The divisor cannot be zero. - */ - function div( - uint256 a, - uint256 b, - string memory errorMessage - ) internal pure returns (uint256) { - require(b > 0, errorMessage); - uint256 c = a / b; - // assert(a == b * c + a % b); // There is no case in which this doesn't hold - - return c; - } - - /** - * @dev Returns the remainder of dividing two unsigned integers. (unsigned integer modulo), - * Reverts when dividing by zero. - * - * Counterpart to Solidity's `%` operator. This function uses a `revert` - * opcode (which leaves remaining gas untouched) while Solidity uses an - * invalid opcode to revert (consuming all remaining gas). - * - * Requirements: - * - * - The divisor cannot be zero. - */ - function mod(uint256 a, uint256 b) internal pure returns (uint256) { - return mod(a, b, "SafeMath: modulo by zero"); - } - - /** - * @dev Returns the remainder of dividing two unsigned integers. (unsigned integer modulo), - * Reverts with custom message when dividing by zero. - * - * Counterpart to Solidity's `%` operator. This function uses a `revert` - * opcode (which leaves remaining gas untouched) while Solidity uses an - * invalid opcode to revert (consuming all remaining gas). - * - * Requirements: - * - * - The divisor cannot be zero. - */ - function mod( - uint256 a, - uint256 b, - string memory errorMessage - ) internal pure returns (uint256) { - require(b != 0, errorMessage); - return a % b; - } - - // babylonian method (https://en.wikipedia.org/wiki/Methods_of_computing_square_roots#Babylonian_method) - function sqrrt(uint256 a) internal pure returns (uint256 c) { - if (a > 3) { - c = a; - uint256 b = add(div(a, 2), 1); - while (b < c) { - c = b; - b = div(add(div(a, b), b), 2); - } - } else if (a != 0) { - c = 1; - } - } - - /* - * Expects percentage to be trailed by 00, - */ - function percentageAmount(uint256 total_, uint8 percentage_) internal pure returns (uint256 percentAmount_) { - return div(mul(total_, percentage_), 1000); - } - - /* - * Expects percentage to be trailed by 00, - */ - function substractPercentage(uint256 total_, uint8 percentageToSub_) internal pure returns (uint256 result_) { - return sub(total_, div(mul(total_, percentageToSub_), 1000)); - } - - function percentageOfTotal(uint256 part_, uint256 total_) internal pure returns (uint256 percent_) { - return div(mul(part_, 100), total_); - } - - /** - * Taken from Hypersonic https://github.com/M2629/HyperSonic/blob/main/Math.sol - * @dev Returns the average of two numbers. The result is rounded towards - * zero. - */ - function average(uint256 a, uint256 b) internal pure returns (uint256) { - // (a + b) / 2 can overflow, so we distribute - return (a / 2) + (b / 2) + (((a % 2) + (b % 2)) / 2); - } - - function quadraticPricing(uint256 payment_, uint256 multiplier_) internal pure returns (uint256) { - return sqrrt(mul(multiplier_, payment_)); - } - - function bondingCurve(uint256 supply_, uint256 multiplier_) internal pure returns (uint256) { - return mul(multiplier_, supply_); - } -} - -// OpenZeppelin Contracts (last updated v4.7.0) (token/ERC20/utils/SafeERC20.sol) - - - - - -// OpenZeppelin Contracts v4.4.1 (token/ERC20/extensions/draft-IERC20Permit.sol) - - - -/** - * @dev Interface of the ERC20 Permit extension allowing approvals to be made via signatures, as defined in - * https://eips.ethereum.org/EIPS/eip-2612[EIP-2612]. - * - * Adds the {permit} method, which can be used to change an account's ERC20 allowance (see {IERC20-allowance}) by - * presenting a message signed by the account. By not relying on {IERC20-approve}, the token holder account doesn't - * need to send a transaction, and thus is not required to hold Ether at all. - */ -interface IERC20Permit { - /** - * @dev Sets `value` as the allowance of `spender` over ``owner``'s tokens, - * given ``owner``'s signed approval. - * - * IMPORTANT: The same issues {IERC20-approve} has related to transaction - * ordering also apply here. - * - * Emits an {Approval} event. - * - * Requirements: - * - * - `spender` cannot be the zero address. - * - `deadline` must be a timestamp in the future. - * - `v`, `r` and `s` must be a valid `secp256k1` signature from `owner` - * over the EIP712-formatted function arguments. - * - the signature must use ``owner``'s current nonce (see {nonces}). - * - * For more information on the signature format, see the - * https://eips.ethereum.org/EIPS/eip-2612#specification[relevant EIP - * section]. - */ - function permit( - address owner, - address spender, - uint256 value, - uint256 deadline, - uint8 v, - bytes32 r, - bytes32 s - ) external; - - /** - * @dev Returns the current nonce for `owner`. This value must be - * included whenever a signature is generated for {permit}. - * - * Every successful call to {permit} increases ``owner``'s nonce by one. This - * prevents a signature from being used multiple times. - */ - function nonces(address owner) external view returns (uint256); - - /** - * @dev Returns the domain separator used in the encoding of the signature for {permit}, as defined by {EIP712}. - */ - // solhint-disable-next-line func-name-mixedcase - function DOMAIN_SEPARATOR() external view returns (bytes32); -} - - - -/** - * @title SafeERC20 - * @dev Wrappers around ERC20 operations that throw on failure (when the token - * contract returns false). Tokens that return no value (and instead revert or - * throw on failure) are also supported, non-reverting calls are assumed to be - * successful. - * To use this library you can add a `using SafeERC20 for IERC20;` statement to your contract, - * which allows you to call the safe operations as `token.safeTransfer(...)`, etc. - */ -library SafeERC20 { - using Address for address; - - function safeTransfer( - IERC20 token, - address to, - uint256 value - ) internal { - _callOptionalReturn(token, abi.encodeWithSelector(token.transfer.selector, to, value)); - } - - function safeTransferFrom( - IERC20 token, - address from, - address to, - uint256 value - ) internal { - _callOptionalReturn(token, abi.encodeWithSelector(token.transferFrom.selector, from, to, value)); - } - - /** - * @dev Deprecated. This function has issues similar to the ones found in - * {IERC20-approve}, and its usage is discouraged. - * - * Whenever possible, use {safeIncreaseAllowance} and - * {safeDecreaseAllowance} instead. - */ - function safeApprove( - IERC20 token, - address spender, - uint256 value - ) internal { - // safeApprove should only be called when setting an initial allowance, - // or when resetting it to zero. To increase and decrease it, use - // 'safeIncreaseAllowance' and 'safeDecreaseAllowance' - require( - (value == 0) || (token.allowance(address(this), spender) == 0), - "SafeERC20: approve from non-zero to non-zero allowance" - ); - _callOptionalReturn(token, abi.encodeWithSelector(token.approve.selector, spender, value)); - } - - function safeIncreaseAllowance( - IERC20 token, - address spender, - uint256 value - ) internal { - uint256 newAllowance = token.allowance(address(this), spender) + value; - _callOptionalReturn(token, abi.encodeWithSelector(token.approve.selector, spender, newAllowance)); - } - - function safeDecreaseAllowance( - IERC20 token, - address spender, - uint256 value - ) internal { - unchecked { - uint256 oldAllowance = token.allowance(address(this), spender); - require(oldAllowance >= value, "SafeERC20: decreased allowance below zero"); - uint256 newAllowance = oldAllowance - value; - _callOptionalReturn(token, abi.encodeWithSelector(token.approve.selector, spender, newAllowance)); - } - } - - function safePermit( - IERC20Permit token, - address owner, - address spender, - uint256 value, - uint256 deadline, - uint8 v, - bytes32 r, - bytes32 s - ) internal { - uint256 nonceBefore = token.nonces(owner); - token.permit(owner, spender, value, deadline, v, r, s); - uint256 nonceAfter = token.nonces(owner); - require(nonceAfter == nonceBefore + 1, "SafeERC20: permit did not succeed"); - } - - /** - * @dev Imitates a Solidity high-level call (i.e. a regular function call to a contract), relaxing the requirement - * on the return value: the return value is optional (but if data is returned, it must not be false). - * @param token The token targeted by the call. - * @param data The call data (encoded using abi.encode or one of its variants). - */ - function _callOptionalReturn(IERC20 token, bytes memory data) private { - // We need to perform a low level call here, to bypass Solidity's return data size checking mechanism, since - // we're implementing it ourselves. We use {Address.functionCall} to perform this call, which verifies that - // the target address contains contract code and also asserts for success in the low-level call. - - bytes memory returndata = address(token).functionCall(data, "SafeERC20: low-level call failed"); - if (returndata.length > 0) { - // Return data is optional - require(abi.decode(returndata, (bool)), "SafeERC20: ERC20 operation did not succeed"); - } - } -} - - - - - - - - - - - - - - -/** - * @dev Provides information about the current execution context, including the - * sender of the transaction and its data. While these are generally available - * via msg.sender and msg.data, they should not be accessed in such a direct - * manner, since when dealing with meta-transactions the account sending and - * paying for execution may not be the actual sender (as far as an application - * is concerned). - * - * This contract is only required for intermediate, library-like contracts. - */ -abstract contract Context { - function _msgSender() internal view virtual returns (address) { - return msg.sender; - } - - function _msgData() internal view virtual returns (bytes calldata) { - return msg.data; - } -} - - -/** - * @dev Contract module which provides a basic access control mechanism, where - * there is an account (an owner) that can be granted exclusive access to - * specific functions. - * - * By default, the owner account will be the one that deploys the contract. This - * can later be changed with {transferOwnership}. - * - * This module is used through inheritance. It will make available the modifier - * `onlyOwner`, which can be applied to your functions to restrict their use to - * the owner. - */ -abstract contract Ownable is Context { - address private _owner; - - event OwnershipTransferred(address indexed previousOwner, address indexed newOwner); - - /** - * @dev Initializes the contract setting the deployer as the initial owner. - */ - constructor() { - _transferOwnership(_msgSender()); - } - - /** - * @dev Throws if called by any account other than the owner. - */ - modifier onlyOwner() { - _checkOwner(); - _; - } - - /** - * @dev Returns the address of the current owner. - */ - function owner() public view virtual returns (address) { - return _owner; - } - - /** - * @dev Throws if the sender is not the owner. - */ - function _checkOwner() internal view virtual { - require(owner() == _msgSender(), "Ownable: caller is not the owner"); - } - - /** - * @dev Leaves the contract without owner. It will not be possible to call - * `onlyOwner` functions anymore. Can only be called by the current owner. - * - * NOTE: Renouncing ownership will leave the contract without an owner, - * thereby removing any functionality that is only available to the owner. - */ - function renounceOwnership() public virtual onlyOwner { - _transferOwnership(address(0)); - } - - /** - * @dev Transfers ownership of the contract to a new account (`newOwner`). - * Can only be called by the current owner. - */ - function transferOwnership(address newOwner) public virtual onlyOwner { - require(newOwner != address(0), "Ownable: new owner is the zero address"); - _transferOwnership(newOwner); - } - - /** - * @dev Transfers ownership of the contract to a new account (`newOwner`). - * Internal function without access restriction. - */ - function _transferOwnership(address newOwner) internal virtual { - address oldOwner = _owner; - _owner = newOwner; - emit OwnershipTransferred(oldOwner, newOwner); - } -} - - -contract Operator is Ownable { - address public operator; - uint256 constant baseRate = 10000; - - modifier onlyOperator { - require(msg.sender == owner() || msg.sender == operator, "no permission"); - _; - } - - function setOperator(address operator_) external onlyOwner { - operator = operator_; - } - - - function getCurrTime() external view returns(uint256) { - return block.timestamp; - } - - function getBlockNum() external view returns(uint256) { - return block.number; - } - -} - - - - - -/** - * @dev Library for managing - * https://en.wikipedia.org/wiki/Set_(abstract_data_type)[sets] of primitive - * types. - * - * Sets have the following properties: - * - * - Elements are added, removed, and checked for existence in constant time - * (O(1)). - * - Elements are enumerated in O(n). No guarantees are made on the ordering. - * - * ``` - * contract Example { - * // Add the library methods - * using EnumerableSet for EnumerableSet.AddressSet; - * - * // Declare a set state variable - * EnumerableSet.AddressSet private mySet; - * } - * ``` - * - * As of v3.3.0, sets of type `bytes32` (`Bytes32Set`), `address` (`AddressSet`) - * and `uint256` (`UintSet`) are supported. - * - * [WARNING] - * ==== - * Trying to delete such a structure from storage will likely result in data corruption, rendering the structure unusable. - * See https://github.com/ethereum/solidity/pull/11843[ethereum/solidity#11843] for more info. - * - * In order to clean an EnumerableSet, you can either remove all elements one by one or create a fresh instance using an array of EnumerableSet. - * ==== - */ - -library EnumerableSet { - // To implement this library for multiple types with as little code - // repetition as possible, we write it in terms of a generic Set type with - // bytes32 values. - // The Set implementation uses private functions, and user-facing - // implementations (such as AddressSet) are just wrappers around the - // underlying Set. - // This means that we can only create new EnumerableSets for types that fit - // in bytes32. - - struct Set { - // Storage of set values - bytes32[] _values; - // Position of the value in the `values` array, plus 1 because index 0 - // means a value is not in the set. - mapping(bytes32 => uint256) _indexes; - } - - /** - * @dev Add a value to a set. O(1). - * - * Returns true if the value was added to the set, that is if it was not - * already present. - */ - function _add(Set storage set, bytes32 value) private returns (bool) { - if (!_contains(set, value)) { - set._values.push(value); - // The value is stored at length-1, but we add 1 to all indexes - // and use 0 as a sentinel value - set._indexes[value] = set._values.length; - return true; - } else { - return false; - } - } - - /** - * @dev Removes a value from a set. O(1). - * - * Returns true if the value was removed from the set, that is if it was - * present. - */ - function _remove(Set storage set, bytes32 value) private returns (bool) { - // We read and store the value's index to prevent multiple reads from the same storage slot - uint256 valueIndex = set._indexes[value]; - - if (valueIndex != 0) { - // Equivalent to contains(set, value) - // To delete an element from the _values array in O(1), we swap the element to delete with the last one in - // the array, and then remove the last element (sometimes called as 'swap and pop'). - // This modifies the order of the array, as noted in {at}. - - uint256 toDeleteIndex = valueIndex - 1; - uint256 lastIndex = set._values.length - 1; - - if (lastIndex != toDeleteIndex) { - bytes32 lastValue = set._values[lastIndex]; - - // Move the last value to the index where the value to delete is - set._values[toDeleteIndex] = lastValue; - // Update the index for the moved value - set._indexes[lastValue] = valueIndex; // Replace lastValue's index to valueIndex - } - - // Delete the slot where the moved value was stored - set._values.pop(); - - // Delete the index for the deleted slot - delete set._indexes[value]; - - return true; - } else { - return false; - } - } - - /** - * @dev Returns true if the value is in the set. O(1). - */ - function _contains(Set storage set, bytes32 value) private view returns (bool) { - return set._indexes[value] != 0; - } - - /** - * @dev Returns the number of values on the set. O(1). - */ - function _length(Set storage set) private view returns (uint256) { - return set._values.length; - } - - /** - * @dev Returns the value stored at position `index` in the set. O(1). - * - * Note that there are no guarantees on the ordering of values inside the - * array, and it may change when more values are added or removed. - * - * Requirements: - * - * - `index` must be strictly less than {length}. - */ - function _at(Set storage set, uint256 index) private view returns (bytes32) { - return set._values[index]; - } - - /** - * @dev Return the entire set in an array - * - * WARNING: This operation will copy the entire storage to memory, which can be quite expensive. This is designed - * to mostly be used by view accessors that are queried without any gas fees. Developers should keep in mind that - * this function has an unbounded cost, and using it as part of a state-changing function may render the function - * uncallable if the set grows to a point where copying to memory consumes too much gas to fit in a block. - */ - function _values(Set storage set) private view returns (bytes32[] memory) { - return set._values; - } - - // Bytes32Set - - struct Bytes32Set { - Set _inner; - } - - /** - * @dev Add a value to a set. O(1). - * - * Returns true if the value was added to the set, that is if it was not - * already present. - */ - function add(Bytes32Set storage set, bytes32 value) internal returns (bool) { - return _add(set._inner, value); - } - - /** - * @dev Removes a value from a set. O(1). - * - * Returns true if the value was removed from the set, that is if it was - * present. - */ - function remove(Bytes32Set storage set, bytes32 value) internal returns (bool) { - return _remove(set._inner, value); - } - - /** - * @dev Returns true if the value is in the set. O(1). - */ - function contains(Bytes32Set storage set, bytes32 value) internal view returns (bool) { - return _contains(set._inner, value); - } - - /** - * @dev Returns the number of values in the set. O(1). - */ - function length(Bytes32Set storage set) internal view returns (uint256) { - return _length(set._inner); - } - - /** - * @dev Returns the value stored at position `index` in the set. O(1). - * - * Note that there are no guarantees on the ordering of values inside the - * array, and it may change when more values are added or removed. - * - * Requirements: - * - * - `index` must be strictly less than {length}. - */ - function at(Bytes32Set storage set, uint256 index) internal view returns (bytes32) { - return _at(set._inner, index); - } - - /** - * @dev Return the entire set in an array - * - * WARNING: This operation will copy the entire storage to memory, which can be quite expensive. This is designed - * to mostly be used by view accessors that are queried without any gas fees. Developers should keep in mind that - * this function has an unbounded cost, and using it as part of a state-changing function may render the function - * uncallable if the set grows to a point where copying to memory consumes too much gas to fit in a block. - */ - function values(Bytes32Set storage set) internal view returns (bytes32[] memory) { - return _values(set._inner); - } - - // AddressSet - - struct AddressSet { - Set _inner; - } - - /** - * @dev Add a value to a set. O(1). - * - * Returns true if the value was added to the set, that is if it was not - * already present. - */ - function add(AddressSet storage set, address value) internal returns (bool) { - return _add(set._inner, bytes32(uint256(uint160(value)))); - } - - /** - * @dev Removes a value from a set. O(1). - * - * Returns true if the value was removed from the set, that is if it was - * present. - */ - function remove(AddressSet storage set, address value) internal returns (bool) { - return _remove(set._inner, bytes32(uint256(uint160(value)))); - } - - /** - * @dev Returns true if the value is in the set. O(1). - */ - function contains(AddressSet storage set, address value) internal view returns (bool) { - return _contains(set._inner, bytes32(uint256(uint160(value)))); - } - - /** - * @dev Returns the number of values in the set. O(1). - */ - function length(AddressSet storage set) internal view returns (uint256) { - return _length(set._inner); - } - - /** - * @dev Returns the value stored at position `index` in the set. O(1). - * - * Note that there are no guarantees on the ordering of values inside the - * array, and it may change when more values are added or removed. - * - * Requirements: - * - * - `index` must be strictly less than {length}. - */ - function at(AddressSet storage set, uint256 index) internal view returns (address) { - return address(uint160(uint256(_at(set._inner, index)))); - } - - /** - * @dev Return the entire set in an array - * - * WARNING: This operation will copy the entire storage to memory, which can be quite expensive. This is designed - * to mostly be used by view accessors that are queried without any gas fees. Developers should keep in mind that - * this function has an unbounded cost, and using it as part of a state-changing function may render the function - * uncallable if the set grows to a point where copying to memory consumes too much gas to fit in a block. - */ - function values(AddressSet storage set) internal view returns (address[] memory) { - bytes32[] memory store = _values(set._inner); - address[] memory result; - - /// @solidity memory-safe-assembly - assembly { - result := store - } - - return result; - } - - // UintSet - - struct UintSet { - Set _inner; - } - - /** - * @dev Add a value to a set. O(1). - * - * Returns true if the value was added to the set, that is if it was not - * already present. - */ - function add(UintSet storage set, uint256 value) internal returns (bool) { - return _add(set._inner, bytes32(value)); - } - - /** - * @dev Removes a value from a set. O(1). - * - * Returns true if the value was removed from the set, that is if it was - * present. - */ - function remove(UintSet storage set, uint256 value) internal returns (bool) { - return _remove(set._inner, bytes32(value)); - } - - /** - * @dev Returns true if the value is in the set. O(1). - */ - function contains(UintSet storage set, uint256 value) internal view returns (bool) { - return _contains(set._inner, bytes32(value)); - } - - /** - * @dev Returns the number of values on the set. O(1). - */ - function length(UintSet storage set) internal view returns (uint256) { - return _length(set._inner); - } - - /** - * @dev Returns the value stored at position `index` in the set. O(1). - * - * Note that there are no guarantees on the ordering of values inside the - * array, and it may change when more values are added or removed. - * - * Requirements: - * - * - `index` must be strictly less than {length}. - */ - function at(UintSet storage set, uint256 index) internal view returns (uint256) { - return uint256(_at(set._inner, index)); - } - - /** - * @dev Return the entire set in an array - * - * WARNING: This operation will copy the entire storage to memory, which can be quite expensive. This is designed - * to mostly be used by view accessors that are queried without any gas fees. Developers should keep in mind that - * this function has an unbounded cost, and using it as part of a state-changing function may render the function - * uncallable if the set grows to a point where copying to memory consumes too much gas to fit in a block. - */ - function values(UintSet storage set) internal view returns (uint256[] memory) { - bytes32[] memory store = _values(set._inner); - uint256[] memory result; - - /// @solidity memory-safe-assembly - assembly { - result := store - } - - return result; - } -} - - -contract ActivityPool is Operator { - using SafeMath for uint256; - using SafeERC20 for IERC20; - using EnumerableSet for EnumerableSet.AddressSet; - using EnumerableSet for EnumerableSet.UintSet; - - event AddNewAct(uint256 id); - event Bet(address user, uint256 pID, uint256 bType, uint256 amount, uint256 time); - event SetPrize(uint256 pID, uint256 bType); - event Claim(address user, uint256 pID, uint256 bType, uint256 amount); - event RemovePeriodAct(uint256 pID); - - uint256 public constant muti = 1e18; - uint256 public periodID; - uint256 public betID; - - struct UserInfo { - address user; - uint256 pID; - uint256 amount; - uint256 betTime; - uint256 bType; - uint256 claimAmount; - } - - struct ActInfo { - string name; - string aName; - string bName; - address rewardToken; - uint256 startTime; - uint256 endTime; - uint256 minAmount; - uint256 maxAmount; - uint256 aAmount; - uint256 bAmount; - uint256 winType; - bool isBet; - } - - struct TimeInfo { - uint256 time; - uint256 aAmount; - uint256 bAmount; - } - - struct BestInfo { - address aUser; - address bUser; - uint256 aBet; - uint256 bBet; - } - - mapping(uint256 => BestInfo) bestInfo; - mapping(uint256 => uint256) public timeID; - mapping(uint256 => mapping(uint256 => TimeInfo)) public timeInfo; - mapping(address => mapping(uint256 => uint256)) public userBet; - mapping(uint256 => UserInfo) public betInfo; - mapping(uint256 => uint256) public perAmount; - mapping(uint256 => ActInfo) public actInfo; - mapping(uint256 => mapping(uint256 => string)) public descripName; - - mapping(address => EnumerableSet.UintSet) userPid; - mapping(uint256 => EnumerableSet.AddressSet) aUsers; - mapping(uint256 => EnumerableSet.AddressSet) bUsers; - EnumerableSet.UintSet activePeriod; - EnumerableSet.UintSet removePeriod; - - function addNewAct( - string memory name, - string memory aName, - string memory bName, - address token, - uint256 startTime, - uint256 endTime, - uint256 minAmount, - uint256 maxAmount - ) external onlyOperator { - - checkAdd(msg.sender, startTime, endTime, minAmount, maxAmount); - uint256 id = ++periodID; - actInfo[id].name = name; - actInfo[id].aName = aName; - actInfo[id].bName = bName; - actInfo[id].startTime = startTime; - actInfo[id].endTime = endTime; - actInfo[id].minAmount = minAmount; - actInfo[id].maxAmount = maxAmount; - actInfo[id].rewardToken = token; - descripName[id][1] = aName; - descripName[id][2] = bName; - activePeriod.add(id); - - emit AddNewAct(id); - } - - - function removePeriodAct(uint256 pID) external onlyOperator { - checkRemove(pID); - - activePeriod.remove(pID); - removePeriod.add(pID); - - emit RemovePeriodAct(pID); - } - - - function bet(uint256 pID, uint256 bType, uint256 amount) external payable { - checkBet(msg.sender, pID, bType, amount); - if(actInfo[pID].rewardToken == address(0)) { - require(msg.value == amount, "value err"); - } else { - require(msg.value == 0, "value amount err"); - } - - if(bType == 1) { - if(amount > bestInfo[pID].aBet) { - bestInfo[pID].aUser = msg.sender; - bestInfo[pID].aBet = amount; - } - } else { - if(amount > bestInfo[pID].bBet) { - bestInfo[pID].bUser = msg.sender; - bestInfo[pID].bBet = amount; - } - } - - userPid[msg.sender].add(pID); - uint256 id = ++betID; - userBet[msg.sender][pID] = id; - - if(bType == 1) { - aUsers[pID].add(msg.sender); - actInfo[pID].aAmount = actInfo[pID].aAmount.add(amount); - } else { - bUsers[pID].add(msg.sender); - actInfo[pID].bAmount = actInfo[pID].bAmount.add(amount); - } - - actInfo[pID].isBet = true; - betInfo[id].user = msg.sender; - betInfo[id].pID = pID; - betInfo[id].amount = amount; - betInfo[id].betTime = block.timestamp; - betInfo[id].bType = bType; - - uint256 tID = ++timeID[pID]; - timeInfo[pID][tID].time = block.timestamp; - timeInfo[pID][tID].aAmount = actInfo[pID].aAmount; - timeInfo[pID][tID].bAmount = actInfo[pID].bAmount; - - if(actInfo[pID].rewardToken != address(0)) { - IERC20(actInfo[pID].rewardToken).safeTransferFrom(msg.sender, address(this), amount); - } - emit Bet(msg.sender, pID, bType, amount, betInfo[id].betTime); - } - - function setPrize(uint256 pID, uint256 bType) external onlyOperator { - checkSetPrize(msg.sender, pID, bType); - - if(block.timestamp <= actInfo[pID].startTime) { - actInfo[pID].startTime = block.timestamp; - - } - actInfo[pID].endTime = block.timestamp; - - actInfo[pID].winType = bType; - perAmount[pID] = getPerAmount(pID, bType); - - emit SetPrize(pID, bType); - } - - function recive() public payable {} - - function claim(uint256 pID) external { - uint256 amount = checkClaim(msg.sender, pID); - - uint256 id = userBet[msg.sender][pID]; - betInfo[id].claimAmount = amount; - if(actInfo[pID].rewardToken != address(0)) { - IERC20(actInfo[pID].rewardToken).safeTransfer(msg.sender, amount); - } else { - payable(msg.sender).transfer(amount); - } - - emit Claim(msg.sender, pID, betInfo[id].bType, amount); - } - - function checkClaim(address user, uint256 pID) public view returns(uint256 amount) { - require(userPid[user].contains(pID), "not bet"); - uint256 id = userBet[user][pID]; - require(betInfo[id].user == user, "not user"); - require(actInfo[pID].winType != 0, "not prize"); - require(betInfo[id].claimAmount == 0, "has claim"); - - if(actInfo[pID].winType != 3) { - require(actInfo[pID].winType == betInfo[id].bType, "not right"); - amount = perAmount[pID].mul(betInfo[id].amount).div(muti); - require(amount > 0, "no amount"); - } else { - amount = betInfo[id].amount; - } - - return amount; - } - - function getActualRate( - address user, - uint256 pID, - uint256 bType, - uint256 amount - ) external view returns(uint256, uint256, bool) { - if(bType < 1 || bType > 2 || !activePeriod.contains(pID)) { - return (0, 0, false); - } else if(userBet[user][pID] != 0 || actInfo[pID].winType != 0 || amount == 0) { - (uint256 ra, uint256 rb) = getRate(pID, timeID[pID]); - return (ra, rb, false); - } else { - (uint256 aAmount, uint256 bAmount) = (actInfo[pID].aAmount, actInfo[pID].bAmount); - if(bType == 1) { - aAmount = aAmount.add(amount); - } else { - bAmount = bAmount.add(amount); - } - - uint256 total = aAmount.add(bAmount); - if(bAmount == 0 && aAmount != 0) { - return (muti, 0, true); - } - if(bAmount != 0 && aAmount == 0) { - return (0, muti, true); - } - return (total.mul(muti).div(aAmount), total.mul(muti).div(bAmount), true); - } - } - - function getRate(uint256 pID, uint256 tID) public view returns(uint256, uint256) { - (uint256 aAmount, uint256 bAmount) = (timeInfo[pID][tID].aAmount, timeInfo[pID][tID].bAmount); - uint256 total = aAmount.add(bAmount); - if(total == 0) { - return (0, 0); - } - if(bAmount == 0 && aAmount != 0) { - return (muti, 0); - } - if(bAmount != 0 && aAmount == 0) { - return (0, muti); - } - return (total.mul(muti).div(aAmount), total.mul(muti).div(bAmount)); - } - - function getBestInfo(uint256 pID) - external - view - returns(address aUser, address bUser, uint256 aBet, uint256 bBet, uint256 aReward, uint256 bReward) - { - aUser = bestInfo[pID].aUser; - bUser = bestInfo[pID].bUser; - aBet = bestInfo[pID].aBet; - bBet = bestInfo[pID].bBet; - aReward = getPerAmount(pID, 1).mul(aBet).div(muti); - bReward = getPerAmount(pID, 2).mul(bBet).div(muti); - } - - function getPerAmount(uint256 pID, uint256 bType) public view returns(uint256) { - uint256 total = actInfo[pID].aAmount.add(actInfo[pID].bAmount); - if(total == 0) { - return 0; - } - - if(actInfo[pID].winType == 3) { - return muti; - } - - if(bType == 1) { - if(actInfo[pID].aAmount == 0 || actInfo[pID].winType == 2) { - return 0; - } - return total.mul(muti).div(actInfo[pID].aAmount); - } - - if(bType == 2) { - if(actInfo[pID].bAmount == 0 || actInfo[pID].winType == 1) { - return 0; - } - return total.mul(muti).div(actInfo[pID].bAmount); - } - - return 0; - - } - - function checkSetPrize(address user, uint256 pID, uint256 bType) public view returns(bool) { - require(user == owner() || user == operator, "no permission"); - require(bType > 0 && bType <= 3, "type err"); - require(activePeriod.contains(pID), "not active"); - require(actInfo[pID].winType == 0, "has set"); - - return true; - } - - function checkBet( - address user, - uint256 pID, - uint256 bType, - uint256 amount - ) public view returns(bool) { - require(activePeriod.contains(pID), "not active"); - require(actInfo[pID].startTime <= block.timestamp, "not start"); - require(actInfo[pID].endTime > block.timestamp, "has end"); - require(!userPid[user].contains(pID), "has bet"); - require(bType > 0 && bType < 3, "type err"); - require(amount >= actInfo[pID].minAmount && amount <= actInfo[pID].maxAmount, "amount err"); - if(actInfo[pID].rewardToken != address(0)) { - require(IERC20(actInfo[pID].rewardToken).allowance(user, address(this)) >= amount, "not approve enough"); - require(IERC20(actInfo[pID].rewardToken).balanceOf(user) >= amount, "not enough"); - } else { - require(user.balance >= amount, "main token err"); - } - - return true; - } - - - function checkRemove(uint256 pID) public view returns(bool) { - require(activePeriod.contains(pID), "not in"); - require(!actInfo[pID].isBet, "has bet"); - - return true; - } - - function checkAdd( - address user, - uint256 startTime, - uint256 endTime, - uint256 minAmount, - uint256 maxAmount - ) public view returns(bool) { - require(user == owner() || user == operator, "no permission"); - require(startTime > block.timestamp, "startTime err"); - require(endTime > startTime, "endTime err"); - require(minAmount > 0 && maxAmount > minAmount, "amount err"); - - return true; - } - - function getStatus(uint256 pID) external view returns(uint256) { - if(!removePeriod.contains(pID) && !activePeriod.contains(pID)) { - return 5; - } else if(removePeriod.contains(pID)) { - return 6; - } else if(block.timestamp < actInfo[pID].startTime) { - return 1; - } else if ( - actInfo[pID].startTime <= block.timestamp && - actInfo[pID].endTime > block.timestamp - ) { - return 2; - } else if (actInfo[pID].endTime <= block.timestamp && actInfo[pID].winType == 0){ - return 3; - } else if(actInfo[pID].winType != 0) { - return 4; - } - return 0; - } - - function getUserPidNum(address user) external view returns(uint256) { - return userPid[user].length(); - } - - function getUserPid(address user, uint256 index) external view returns(uint256) { - return userPid[user].at(index); - } - - function getAUsersNum(uint256 pID) external view returns(uint256) { - return aUsers[pID].length(); - } - - function getAUsers(uint256 pID, uint256 index) external view returns(address) { - return aUsers[pID].at(index); - } - - function getBUsersNum(uint256 pID) external view returns(uint256) { - return bUsers[pID].length(); - } - - function getBUsers(uint256 pID, uint256 index) external view returns(address) { - return bUsers[pID].at(index); - } - - function getActivePeriodNum() external view returns(uint256) { - return activePeriod.length(); - } - - function getActivePeriod(uint256 index) external view returns(uint256) { - return activePeriod.at(index); - } - - function getRemovePeriodNum() external view returns(uint256) { - return removePeriod.length(); - } - - function getRemovePeriod(uint256 index) external view returns(uint256) { - return removePeriod.at(index); - } -} \ No newline at end of file diff --git a/app/api/uploads/ActivityPool-1729791081574-279065936.sol b/app/api/uploads/ActivityPool-1729791081574-279065936.sol deleted file mode 100644 index daf3372..0000000 --- a/app/api/uploads/ActivityPool-1729791081574-279065936.sol +++ /dev/null @@ -1,1648 +0,0 @@ -// SPDX-License-Identifier: MIT -// OpenZeppelin Contracts (last updated v4.7.0) (utils/Address.sol) - -pragma solidity ^0.8.1; - -/** - * @dev Collection of functions related to the address type - */ -library Address { - /** - * @dev Returns true if `account` is a contract. - * - * [IMPORTANT] - * ==== - * It is unsafe to assume that an address for which this function returns - * false is an externally-owned account (EOA) and not a contract. - * - * Among others, `isContract` will return false for the following - * types of addresses: - * - * - an externally-owned account - * - a contract in construction - * - an address where a contract will be created - * - an address where a contract lived, but was destroyed - * ==== - * - * [IMPORTANT] - * ==== - * You shouldn't rely on `isContract` to protect against flash loan attacks! - * - * Preventing calls from contracts is highly discouraged. It breaks composability, breaks support for smart wallets - * like Gnosis Safe, and does not provide security since it can be circumvented by calling from a contract - * constructor. - * ==== - */ - function isContract(address account) internal view returns (bool) { - // This method relies on extcodesize/address.code.length, which returns 0 - // for contracts in construction, since the code is only stored at the end - // of the constructor execution. - - return account.code.length > 0; - } - - /** - * @dev Replacement for Solidity's `transfer`: sends `amount` wei to - * `recipient`, forwarding all available gas and reverting on errors. - * - * https://eips.ethereum.org/EIPS/eip-1884[EIP1884] increases the gas cost - * of certain opcodes, possibly making contracts go over the 2300 gas limit - * imposed by `transfer`, making them unable to receive funds via - * `transfer`. {sendValue} removes this limitation. - * - * https://diligence.consensys.net/posts/2019/09/stop-using-soliditys-transfer-now/[Learn more]. - * - * IMPORTANT: because control is transferred to `recipient`, care must be - * taken to not create reentrancy vulnerabilities. Consider using - * {ReentrancyGuard} or the - * https://solidity.readthedocs.io/en/v0.5.11/security-considerations.html#use-the-checks-effects-interactions-pattern[checks-effects-interactions pattern]. - */ - function sendValue(address payable recipient, uint256 amount) internal { - require(address(this).balance >= amount, "Address: insufficient balance"); - - (bool success, ) = recipient.call{value: amount}(""); - require(success, "Address: unable to send value, recipient may have reverted"); - } - - /** - * @dev Performs a Solidity function call using a low level `call`. A - * plain `call` is an unsafe replacement for a function call: use this - * function instead. - * - * If `target` reverts with a revert reason, it is bubbled up by this - * function (like regular Solidity function calls). - * - * Returns the raw returned data. To convert to the expected return value, - * use https://solidity.readthedocs.io/en/latest/units-and-global-variables.html?highlight=abi.decode#abi-encoding-and-decoding-functions[`abi.decode`]. - * - * Requirements: - * - * - `target` must be a contract. - * - calling `target` with `data` must not revert. - * - * _Available since v3.1._ - */ - function functionCall(address target, bytes memory data) internal returns (bytes memory) { - return functionCallWithValue(target, data, 0, "Address: low-level call failed"); - } - - /** - * @dev Same as {xref-Address-functionCall-address-bytes-}[`functionCall`], but with - * `errorMessage` as a fallback revert reason when `target` reverts. - * - * _Available since v3.1._ - */ - function functionCall( - address target, - bytes memory data, - string memory errorMessage - ) internal returns (bytes memory) { - return functionCallWithValue(target, data, 0, errorMessage); - } - - /** - * @dev Same as {xref-Address-functionCall-address-bytes-}[`functionCall`], - * but also transferring `value` wei to `target`. - * - * Requirements: - * - * - the calling contract must have an ETH balance of at least `value`. - * - the called Solidity function must be `payable`. - * - * _Available since v3.1._ - */ - function functionCallWithValue( - address target, - bytes memory data, - uint256 value - ) internal returns (bytes memory) { - return functionCallWithValue(target, data, value, "Address: low-level call with value failed"); - } - - /** - * @dev Same as {xref-Address-functionCallWithValue-address-bytes-uint256-}[`functionCallWithValue`], but - * with `errorMessage` as a fallback revert reason when `target` reverts. - * - * _Available since v3.1._ - */ - function functionCallWithValue( - address target, - bytes memory data, - uint256 value, - string memory errorMessage - ) internal returns (bytes memory) { - require(address(this).balance >= value, "Address: insufficient balance for call"); - (bool success, bytes memory returndata) = target.call{value: value}(data); - return verifyCallResultFromTarget(target, success, returndata, errorMessage); - } - - /** - * @dev Same as {xref-Address-functionCall-address-bytes-}[`functionCall`], - * but performing a static call. - * - * _Available since v3.3._ - */ - function functionStaticCall(address target, bytes memory data) internal view returns (bytes memory) { - return functionStaticCall(target, data, "Address: low-level static call failed"); - } - - /** - * @dev Same as {xref-Address-functionCall-address-bytes-string-}[`functionCall`], - * but performing a static call. - * - * _Available since v3.3._ - */ - function functionStaticCall( - address target, - bytes memory data, - string memory errorMessage - ) internal view returns (bytes memory) { - (bool success, bytes memory returndata) = target.staticcall(data); - return verifyCallResultFromTarget(target, success, returndata, errorMessage); - } - - /** - * @dev Same as {xref-Address-functionCall-address-bytes-}[`functionCall`], - * but performing a delegate call. - * - * _Available since v3.4._ - */ - function functionDelegateCall(address target, bytes memory data) internal returns (bytes memory) { - return functionDelegateCall(target, data, "Address: low-level delegate call failed"); - } - - /** - * @dev Same as {xref-Address-functionCall-address-bytes-string-}[`functionCall`], - * but performing a delegate call. - * - * _Available since v3.4._ - */ - function functionDelegateCall( - address target, - bytes memory data, - string memory errorMessage - ) internal returns (bytes memory) { - (bool success, bytes memory returndata) = target.delegatecall(data); - return verifyCallResultFromTarget(target, success, returndata, errorMessage); - } - - /** - * @dev Tool to verify that a low level call to smart-contract was successful, and revert (either by bubbling - * the revert reason or using the provided one) in case of unsuccessful call or if target was not a contract. - * - * _Available since v4.8._ - */ - function verifyCallResultFromTarget( - address target, - bool success, - bytes memory returndata, - string memory errorMessage - ) internal view returns (bytes memory) { - if (success) { - if (returndata.length == 0) { - // only check isContract if the call was successful and the return data is empty - // otherwise we already know that it was a contract - require(isContract(target), "Address: call to non-contract"); - } - return returndata; - } else { - _revert(returndata, errorMessage); - } - } - - /** - * @dev Tool to verify that a low level call was successful, and revert if it wasn't, either by bubbling the - * revert reason or using the provided one. - * - * _Available since v4.3._ - */ - function verifyCallResult( - bool success, - bytes memory returndata, - string memory errorMessage - ) internal pure returns (bytes memory) { - if (success) { - return returndata; - } else { - _revert(returndata, errorMessage); - } - } - - function _revert(bytes memory returndata, string memory errorMessage) private pure { - // Look for revert reason and bubble it up if present - if (returndata.length > 0) { - // The easiest way to bubble the revert reason is using memory via assembly - /// @solidity memory-safe-assembly - assembly { - let returndata_size := mload(returndata) - revert(add(32, returndata), returndata_size) - } - } else { - revert(errorMessage); - } - } -} - -// OpenZeppelin Contracts (last updated v4.6.0) (token/ERC20/IERC20.sol) - - - -/** - * @dev Interface of the ERC20 standard as defined in the EIP. - */ -interface IERC20 { - /** - * @dev Emitted when `value` tokens are moved from one account (`from`) to - * another (`to`). - * - * Note that `value` may be zero. - */ - event Transfer(address indexed from, address indexed to, uint256 value); - - /** - * @dev Emitted when the allowance of a `spender` for an `owner` is set by - * a call to {approve}. `value` is the new allowance. - */ - event Approval(address indexed owner, address indexed spender, uint256 value); - - /** - * @dev Returns the amount of tokens in existence. - */ - function totalSupply() external view returns (uint256); - - /** - * @dev Returns the amount of tokens owned by `account`. - */ - function balanceOf(address account) external view returns (uint256); - - /** - * @dev Moves `amount` tokens from the caller's account to `to`. - * - * Returns a boolean value indicating whether the operation succeeded. - * - * Emits a {Transfer} event. - */ - function transfer(address to, uint256 amount) external returns (bool); - - /** - * @dev Returns the remaining number of tokens that `spender` will be - * allowed to spend on behalf of `owner` through {transferFrom}. This is - * zero by default. - * - * This value changes when {approve} or {transferFrom} are called. - */ - function allowance(address owner, address spender) external view returns (uint256); - - /** - * @dev Sets `amount` as the allowance of `spender` over the caller's tokens. - * - * Returns a boolean value indicating whether the operation succeeded. - * - * IMPORTANT: Beware that changing an allowance with this method brings the risk - * that someone may use both the old and the new allowance by unfortunate - * transaction ordering. One possible solution to mitigate this race - * condition is to first reduce the spender's allowance to 0 and set the - * desired value afterwards: - * https://github.com/ethereum/EIPs/issues/20#issuecomment-263524729 - * - * Emits an {Approval} event. - */ - function approve(address spender, uint256 amount) external returns (bool); - - /** - * @dev Moves `amount` tokens from `from` to `to` using the - * allowance mechanism. `amount` is then deducted from the caller's - * allowance. - * - * Returns a boolean value indicating whether the operation succeeded. - * - * Emits a {Transfer} event. - */ - function transferFrom( - address from, - address to, - uint256 amount - ) external returns (bool); - - - function mint(address account_, uint256 amount_) external; - - function burn(uint256 amount) external; - -} - - - - - - - - - - - -/** - * @dev Wrappers over Solidity's arithmetic operations with added overflow - * checks. - * - * Arithmetic operations in Solidity wrap on overflow. This can easily result - * in bugs, because programmers usually assume that an overflow raises an - * error, which is the standard behavior in high level programming languages. - * `SafeMath` restores this intuition by reverting the transaction when an - * operation overflows. - * - * Using this library instead of the unchecked operations eliminates an entire - * class of bugs, so it's recommended to use it always. - */ -library SafeMath { - /** - * @dev Returns the addition of two unsigned integers, reverting on - * overflow. - * - * Counterpart to Solidity's `+` operator. - * - * Requirements: - * - * - Addition cannot overflow. - */ - function add(uint256 a, uint256 b) internal pure returns (uint256) { - uint256 c = a + b; - require(c >= a, "SafeMath: addition overflow"); - - return c; - } - - /** - * @dev Returns the subtraction of two unsigned integers, reverting on - * overflow (when the result is negative). - * - * Counterpart to Solidity's `-` operator. - * - * Requirements: - * - * - Subtraction cannot overflow. - */ - function sub(uint256 a, uint256 b) internal pure returns (uint256) { - return sub(a, b, "SafeMath: subtraction overflow"); - } - - /** - * @dev Returns the subtraction of two unsigned integers, reverting with custom message on - * overflow (when the result is negative). - * - * Counterpart to Solidity's `-` operator. - * - * Requirements: - * - * - Subtraction cannot overflow. - */ - function sub( - uint256 a, - uint256 b, - string memory errorMessage - ) internal pure returns (uint256) { - require(b <= a, errorMessage); - uint256 c = a - b; - - return c; - } - - /** - * @dev Returns the multiplication of two unsigned integers, reverting on - * overflow. - * - * Counterpart to Solidity's `*` operator. - * - * Requirements: - * - * - Multiplication cannot overflow. - */ - function mul(uint256 a, uint256 b) internal pure returns (uint256) { - // Gas optimization: this is cheaper than requiring 'a' not being zero, but the - // benefit is lost if 'b' is also tested. - // See: https://github.com/OpenZeppelin/openzeppelin-contracts/pull/522 - if (a == 0) { - return 0; - } - - uint256 c = a * b; - require(c / a == b, "SafeMath: multiplication overflow"); - - return c; - } - - /** - * @dev Returns the integer division of two unsigned integers. Reverts on - * division by zero. The result is rounded towards zero. - * - * Counterpart to Solidity's `/` operator. Note: this function uses a - * `revert` opcode (which leaves remaining gas untouched) while Solidity - * uses an invalid opcode to revert (consuming all remaining gas). - * - * Requirements: - * - * - The divisor cannot be zero. - */ - function div(uint256 a, uint256 b) internal pure returns (uint256) { - return div(a, b, "SafeMath: division by zero"); - } - - /** - * @dev Returns the integer division of two unsigned integers. Reverts with custom message on - * division by zero. The result is rounded towards zero. - * - * Counterpart to Solidity's `/` operator. Note: this function uses a - * `revert` opcode (which leaves remaining gas untouched) while Solidity - * uses an invalid opcode to revert (consuming all remaining gas). - * - * Requirements: - * - * - The divisor cannot be zero. - */ - function div( - uint256 a, - uint256 b, - string memory errorMessage - ) internal pure returns (uint256) { - require(b > 0, errorMessage); - uint256 c = a / b; - // assert(a == b * c + a % b); // There is no case in which this doesn't hold - - return c; - } - - /** - * @dev Returns the remainder of dividing two unsigned integers. (unsigned integer modulo), - * Reverts when dividing by zero. - * - * Counterpart to Solidity's `%` operator. This function uses a `revert` - * opcode (which leaves remaining gas untouched) while Solidity uses an - * invalid opcode to revert (consuming all remaining gas). - * - * Requirements: - * - * - The divisor cannot be zero. - */ - function mod(uint256 a, uint256 b) internal pure returns (uint256) { - return mod(a, b, "SafeMath: modulo by zero"); - } - - /** - * @dev Returns the remainder of dividing two unsigned integers. (unsigned integer modulo), - * Reverts with custom message when dividing by zero. - * - * Counterpart to Solidity's `%` operator. This function uses a `revert` - * opcode (which leaves remaining gas untouched) while Solidity uses an - * invalid opcode to revert (consuming all remaining gas). - * - * Requirements: - * - * - The divisor cannot be zero. - */ - function mod( - uint256 a, - uint256 b, - string memory errorMessage - ) internal pure returns (uint256) { - require(b != 0, errorMessage); - return a % b; - } - - // babylonian method (https://en.wikipedia.org/wiki/Methods_of_computing_square_roots#Babylonian_method) - function sqrrt(uint256 a) internal pure returns (uint256 c) { - if (a > 3) { - c = a; - uint256 b = add(div(a, 2), 1); - while (b < c) { - c = b; - b = div(add(div(a, b), b), 2); - } - } else if (a != 0) { - c = 1; - } - } - - /* - * Expects percentage to be trailed by 00, - */ - function percentageAmount(uint256 total_, uint8 percentage_) internal pure returns (uint256 percentAmount_) { - return div(mul(total_, percentage_), 1000); - } - - /* - * Expects percentage to be trailed by 00, - */ - function substractPercentage(uint256 total_, uint8 percentageToSub_) internal pure returns (uint256 result_) { - return sub(total_, div(mul(total_, percentageToSub_), 1000)); - } - - function percentageOfTotal(uint256 part_, uint256 total_) internal pure returns (uint256 percent_) { - return div(mul(part_, 100), total_); - } - - /** - * Taken from Hypersonic https://github.com/M2629/HyperSonic/blob/main/Math.sol - * @dev Returns the average of two numbers. The result is rounded towards - * zero. - */ - function average(uint256 a, uint256 b) internal pure returns (uint256) { - // (a + b) / 2 can overflow, so we distribute - return (a / 2) + (b / 2) + (((a % 2) + (b % 2)) / 2); - } - - function quadraticPricing(uint256 payment_, uint256 multiplier_) internal pure returns (uint256) { - return sqrrt(mul(multiplier_, payment_)); - } - - function bondingCurve(uint256 supply_, uint256 multiplier_) internal pure returns (uint256) { - return mul(multiplier_, supply_); - } -} - -// OpenZeppelin Contracts (last updated v4.7.0) (token/ERC20/utils/SafeERC20.sol) - - - - - -// OpenZeppelin Contracts v4.4.1 (token/ERC20/extensions/draft-IERC20Permit.sol) - - - -/** - * @dev Interface of the ERC20 Permit extension allowing approvals to be made via signatures, as defined in - * https://eips.ethereum.org/EIPS/eip-2612[EIP-2612]. - * - * Adds the {permit} method, which can be used to change an account's ERC20 allowance (see {IERC20-allowance}) by - * presenting a message signed by the account. By not relying on {IERC20-approve}, the token holder account doesn't - * need to send a transaction, and thus is not required to hold Ether at all. - */ -interface IERC20Permit { - /** - * @dev Sets `value` as the allowance of `spender` over ``owner``'s tokens, - * given ``owner``'s signed approval. - * - * IMPORTANT: The same issues {IERC20-approve} has related to transaction - * ordering also apply here. - * - * Emits an {Approval} event. - * - * Requirements: - * - * - `spender` cannot be the zero address. - * - `deadline` must be a timestamp in the future. - * - `v`, `r` and `s` must be a valid `secp256k1` signature from `owner` - * over the EIP712-formatted function arguments. - * - the signature must use ``owner``'s current nonce (see {nonces}). - * - * For more information on the signature format, see the - * https://eips.ethereum.org/EIPS/eip-2612#specification[relevant EIP - * section]. - */ - function permit( - address owner, - address spender, - uint256 value, - uint256 deadline, - uint8 v, - bytes32 r, - bytes32 s - ) external; - - /** - * @dev Returns the current nonce for `owner`. This value must be - * included whenever a signature is generated for {permit}. - * - * Every successful call to {permit} increases ``owner``'s nonce by one. This - * prevents a signature from being used multiple times. - */ - function nonces(address owner) external view returns (uint256); - - /** - * @dev Returns the domain separator used in the encoding of the signature for {permit}, as defined by {EIP712}. - */ - // solhint-disable-next-line func-name-mixedcase - function DOMAIN_SEPARATOR() external view returns (bytes32); -} - - - -/** - * @title SafeERC20 - * @dev Wrappers around ERC20 operations that throw on failure (when the token - * contract returns false). Tokens that return no value (and instead revert or - * throw on failure) are also supported, non-reverting calls are assumed to be - * successful. - * To use this library you can add a `using SafeERC20 for IERC20;` statement to your contract, - * which allows you to call the safe operations as `token.safeTransfer(...)`, etc. - */ -library SafeERC20 { - using Address for address; - - function safeTransfer( - IERC20 token, - address to, - uint256 value - ) internal { - _callOptionalReturn(token, abi.encodeWithSelector(token.transfer.selector, to, value)); - } - - function safeTransferFrom( - IERC20 token, - address from, - address to, - uint256 value - ) internal { - _callOptionalReturn(token, abi.encodeWithSelector(token.transferFrom.selector, from, to, value)); - } - - /** - * @dev Deprecated. This function has issues similar to the ones found in - * {IERC20-approve}, and its usage is discouraged. - * - * Whenever possible, use {safeIncreaseAllowance} and - * {safeDecreaseAllowance} instead. - */ - function safeApprove( - IERC20 token, - address spender, - uint256 value - ) internal { - // safeApprove should only be called when setting an initial allowance, - // or when resetting it to zero. To increase and decrease it, use - // 'safeIncreaseAllowance' and 'safeDecreaseAllowance' - require( - (value == 0) || (token.allowance(address(this), spender) == 0), - "SafeERC20: approve from non-zero to non-zero allowance" - ); - _callOptionalReturn(token, abi.encodeWithSelector(token.approve.selector, spender, value)); - } - - function safeIncreaseAllowance( - IERC20 token, - address spender, - uint256 value - ) internal { - uint256 newAllowance = token.allowance(address(this), spender) + value; - _callOptionalReturn(token, abi.encodeWithSelector(token.approve.selector, spender, newAllowance)); - } - - function safeDecreaseAllowance( - IERC20 token, - address spender, - uint256 value - ) internal { - unchecked { - uint256 oldAllowance = token.allowance(address(this), spender); - require(oldAllowance >= value, "SafeERC20: decreased allowance below zero"); - uint256 newAllowance = oldAllowance - value; - _callOptionalReturn(token, abi.encodeWithSelector(token.approve.selector, spender, newAllowance)); - } - } - - function safePermit( - IERC20Permit token, - address owner, - address spender, - uint256 value, - uint256 deadline, - uint8 v, - bytes32 r, - bytes32 s - ) internal { - uint256 nonceBefore = token.nonces(owner); - token.permit(owner, spender, value, deadline, v, r, s); - uint256 nonceAfter = token.nonces(owner); - require(nonceAfter == nonceBefore + 1, "SafeERC20: permit did not succeed"); - } - - /** - * @dev Imitates a Solidity high-level call (i.e. a regular function call to a contract), relaxing the requirement - * on the return value: the return value is optional (but if data is returned, it must not be false). - * @param token The token targeted by the call. - * @param data The call data (encoded using abi.encode or one of its variants). - */ - function _callOptionalReturn(IERC20 token, bytes memory data) private { - // We need to perform a low level call here, to bypass Solidity's return data size checking mechanism, since - // we're implementing it ourselves. We use {Address.functionCall} to perform this call, which verifies that - // the target address contains contract code and also asserts for success in the low-level call. - - bytes memory returndata = address(token).functionCall(data, "SafeERC20: low-level call failed"); - if (returndata.length > 0) { - // Return data is optional - require(abi.decode(returndata, (bool)), "SafeERC20: ERC20 operation did not succeed"); - } - } -} - - - - - - - - - - - - - - -/** - * @dev Provides information about the current execution context, including the - * sender of the transaction and its data. While these are generally available - * via msg.sender and msg.data, they should not be accessed in such a direct - * manner, since when dealing with meta-transactions the account sending and - * paying for execution may not be the actual sender (as far as an application - * is concerned). - * - * This contract is only required for intermediate, library-like contracts. - */ -abstract contract Context { - function _msgSender() internal view virtual returns (address) { - return msg.sender; - } - - function _msgData() internal view virtual returns (bytes calldata) { - return msg.data; - } -} - - -/** - * @dev Contract module which provides a basic access control mechanism, where - * there is an account (an owner) that can be granted exclusive access to - * specific functions. - * - * By default, the owner account will be the one that deploys the contract. This - * can later be changed with {transferOwnership}. - * - * This module is used through inheritance. It will make available the modifier - * `onlyOwner`, which can be applied to your functions to restrict their use to - * the owner. - */ -abstract contract Ownable is Context { - address private _owner; - - event OwnershipTransferred(address indexed previousOwner, address indexed newOwner); - - /** - * @dev Initializes the contract setting the deployer as the initial owner. - */ - constructor() { - _transferOwnership(_msgSender()); - } - - /** - * @dev Throws if called by any account other than the owner. - */ - modifier onlyOwner() { - _checkOwner(); - _; - } - - /** - * @dev Returns the address of the current owner. - */ - function owner() public view virtual returns (address) { - return _owner; - } - - /** - * @dev Throws if the sender is not the owner. - */ - function _checkOwner() internal view virtual { - require(owner() == _msgSender(), "Ownable: caller is not the owner"); - } - - /** - * @dev Leaves the contract without owner. It will not be possible to call - * `onlyOwner` functions anymore. Can only be called by the current owner. - * - * NOTE: Renouncing ownership will leave the contract without an owner, - * thereby removing any functionality that is only available to the owner. - */ - function renounceOwnership() public virtual onlyOwner { - _transferOwnership(address(0)); - } - - /** - * @dev Transfers ownership of the contract to a new account (`newOwner`). - * Can only be called by the current owner. - */ - function transferOwnership(address newOwner) public virtual onlyOwner { - require(newOwner != address(0), "Ownable: new owner is the zero address"); - _transferOwnership(newOwner); - } - - /** - * @dev Transfers ownership of the contract to a new account (`newOwner`). - * Internal function without access restriction. - */ - function _transferOwnership(address newOwner) internal virtual { - address oldOwner = _owner; - _owner = newOwner; - emit OwnershipTransferred(oldOwner, newOwner); - } -} - - -contract Operator is Ownable { - address public operator; - uint256 constant baseRate = 10000; - - modifier onlyOperator { - require(msg.sender == owner() || msg.sender == operator, "no permission"); - _; - } - - function setOperator(address operator_) external onlyOwner { - operator = operator_; - } - - - function getCurrTime() external view returns(uint256) { - return block.timestamp; - } - - function getBlockNum() external view returns(uint256) { - return block.number; - } - -} - - - - - -/** - * @dev Library for managing - * https://en.wikipedia.org/wiki/Set_(abstract_data_type)[sets] of primitive - * types. - * - * Sets have the following properties: - * - * - Elements are added, removed, and checked for existence in constant time - * (O(1)). - * - Elements are enumerated in O(n). No guarantees are made on the ordering. - * - * ``` - * contract Example { - * // Add the library methods - * using EnumerableSet for EnumerableSet.AddressSet; - * - * // Declare a set state variable - * EnumerableSet.AddressSet private mySet; - * } - * ``` - * - * As of v3.3.0, sets of type `bytes32` (`Bytes32Set`), `address` (`AddressSet`) - * and `uint256` (`UintSet`) are supported. - * - * [WARNING] - * ==== - * Trying to delete such a structure from storage will likely result in data corruption, rendering the structure unusable. - * See https://github.com/ethereum/solidity/pull/11843[ethereum/solidity#11843] for more info. - * - * In order to clean an EnumerableSet, you can either remove all elements one by one or create a fresh instance using an array of EnumerableSet. - * ==== - */ - -library EnumerableSet { - // To implement this library for multiple types with as little code - // repetition as possible, we write it in terms of a generic Set type with - // bytes32 values. - // The Set implementation uses private functions, and user-facing - // implementations (such as AddressSet) are just wrappers around the - // underlying Set. - // This means that we can only create new EnumerableSets for types that fit - // in bytes32. - - struct Set { - // Storage of set values - bytes32[] _values; - // Position of the value in the `values` array, plus 1 because index 0 - // means a value is not in the set. - mapping(bytes32 => uint256) _indexes; - } - - /** - * @dev Add a value to a set. O(1). - * - * Returns true if the value was added to the set, that is if it was not - * already present. - */ - function _add(Set storage set, bytes32 value) private returns (bool) { - if (!_contains(set, value)) { - set._values.push(value); - // The value is stored at length-1, but we add 1 to all indexes - // and use 0 as a sentinel value - set._indexes[value] = set._values.length; - return true; - } else { - return false; - } - } - - /** - * @dev Removes a value from a set. O(1). - * - * Returns true if the value was removed from the set, that is if it was - * present. - */ - function _remove(Set storage set, bytes32 value) private returns (bool) { - // We read and store the value's index to prevent multiple reads from the same storage slot - uint256 valueIndex = set._indexes[value]; - - if (valueIndex != 0) { - // Equivalent to contains(set, value) - // To delete an element from the _values array in O(1), we swap the element to delete with the last one in - // the array, and then remove the last element (sometimes called as 'swap and pop'). - // This modifies the order of the array, as noted in {at}. - - uint256 toDeleteIndex = valueIndex - 1; - uint256 lastIndex = set._values.length - 1; - - if (lastIndex != toDeleteIndex) { - bytes32 lastValue = set._values[lastIndex]; - - // Move the last value to the index where the value to delete is - set._values[toDeleteIndex] = lastValue; - // Update the index for the moved value - set._indexes[lastValue] = valueIndex; // Replace lastValue's index to valueIndex - } - - // Delete the slot where the moved value was stored - set._values.pop(); - - // Delete the index for the deleted slot - delete set._indexes[value]; - - return true; - } else { - return false; - } - } - - /** - * @dev Returns true if the value is in the set. O(1). - */ - function _contains(Set storage set, bytes32 value) private view returns (bool) { - return set._indexes[value] != 0; - } - - /** - * @dev Returns the number of values on the set. O(1). - */ - function _length(Set storage set) private view returns (uint256) { - return set._values.length; - } - - /** - * @dev Returns the value stored at position `index` in the set. O(1). - * - * Note that there are no guarantees on the ordering of values inside the - * array, and it may change when more values are added or removed. - * - * Requirements: - * - * - `index` must be strictly less than {length}. - */ - function _at(Set storage set, uint256 index) private view returns (bytes32) { - return set._values[index]; - } - - /** - * @dev Return the entire set in an array - * - * WARNING: This operation will copy the entire storage to memory, which can be quite expensive. This is designed - * to mostly be used by view accessors that are queried without any gas fees. Developers should keep in mind that - * this function has an unbounded cost, and using it as part of a state-changing function may render the function - * uncallable if the set grows to a point where copying to memory consumes too much gas to fit in a block. - */ - function _values(Set storage set) private view returns (bytes32[] memory) { - return set._values; - } - - // Bytes32Set - - struct Bytes32Set { - Set _inner; - } - - /** - * @dev Add a value to a set. O(1). - * - * Returns true if the value was added to the set, that is if it was not - * already present. - */ - function add(Bytes32Set storage set, bytes32 value) internal returns (bool) { - return _add(set._inner, value); - } - - /** - * @dev Removes a value from a set. O(1). - * - * Returns true if the value was removed from the set, that is if it was - * present. - */ - function remove(Bytes32Set storage set, bytes32 value) internal returns (bool) { - return _remove(set._inner, value); - } - - /** - * @dev Returns true if the value is in the set. O(1). - */ - function contains(Bytes32Set storage set, bytes32 value) internal view returns (bool) { - return _contains(set._inner, value); - } - - /** - * @dev Returns the number of values in the set. O(1). - */ - function length(Bytes32Set storage set) internal view returns (uint256) { - return _length(set._inner); - } - - /** - * @dev Returns the value stored at position `index` in the set. O(1). - * - * Note that there are no guarantees on the ordering of values inside the - * array, and it may change when more values are added or removed. - * - * Requirements: - * - * - `index` must be strictly less than {length}. - */ - function at(Bytes32Set storage set, uint256 index) internal view returns (bytes32) { - return _at(set._inner, index); - } - - /** - * @dev Return the entire set in an array - * - * WARNING: This operation will copy the entire storage to memory, which can be quite expensive. This is designed - * to mostly be used by view accessors that are queried without any gas fees. Developers should keep in mind that - * this function has an unbounded cost, and using it as part of a state-changing function may render the function - * uncallable if the set grows to a point where copying to memory consumes too much gas to fit in a block. - */ - function values(Bytes32Set storage set) internal view returns (bytes32[] memory) { - return _values(set._inner); - } - - // AddressSet - - struct AddressSet { - Set _inner; - } - - /** - * @dev Add a value to a set. O(1). - * - * Returns true if the value was added to the set, that is if it was not - * already present. - */ - function add(AddressSet storage set, address value) internal returns (bool) { - return _add(set._inner, bytes32(uint256(uint160(value)))); - } - - /** - * @dev Removes a value from a set. O(1). - * - * Returns true if the value was removed from the set, that is if it was - * present. - */ - function remove(AddressSet storage set, address value) internal returns (bool) { - return _remove(set._inner, bytes32(uint256(uint160(value)))); - } - - /** - * @dev Returns true if the value is in the set. O(1). - */ - function contains(AddressSet storage set, address value) internal view returns (bool) { - return _contains(set._inner, bytes32(uint256(uint160(value)))); - } - - /** - * @dev Returns the number of values in the set. O(1). - */ - function length(AddressSet storage set) internal view returns (uint256) { - return _length(set._inner); - } - - /** - * @dev Returns the value stored at position `index` in the set. O(1). - * - * Note that there are no guarantees on the ordering of values inside the - * array, and it may change when more values are added or removed. - * - * Requirements: - * - * - `index` must be strictly less than {length}. - */ - function at(AddressSet storage set, uint256 index) internal view returns (address) { - return address(uint160(uint256(_at(set._inner, index)))); - } - - /** - * @dev Return the entire set in an array - * - * WARNING: This operation will copy the entire storage to memory, which can be quite expensive. This is designed - * to mostly be used by view accessors that are queried without any gas fees. Developers should keep in mind that - * this function has an unbounded cost, and using it as part of a state-changing function may render the function - * uncallable if the set grows to a point where copying to memory consumes too much gas to fit in a block. - */ - function values(AddressSet storage set) internal view returns (address[] memory) { - bytes32[] memory store = _values(set._inner); - address[] memory result; - - /// @solidity memory-safe-assembly - assembly { - result := store - } - - return result; - } - - // UintSet - - struct UintSet { - Set _inner; - } - - /** - * @dev Add a value to a set. O(1). - * - * Returns true if the value was added to the set, that is if it was not - * already present. - */ - function add(UintSet storage set, uint256 value) internal returns (bool) { - return _add(set._inner, bytes32(value)); - } - - /** - * @dev Removes a value from a set. O(1). - * - * Returns true if the value was removed from the set, that is if it was - * present. - */ - function remove(UintSet storage set, uint256 value) internal returns (bool) { - return _remove(set._inner, bytes32(value)); - } - - /** - * @dev Returns true if the value is in the set. O(1). - */ - function contains(UintSet storage set, uint256 value) internal view returns (bool) { - return _contains(set._inner, bytes32(value)); - } - - /** - * @dev Returns the number of values on the set. O(1). - */ - function length(UintSet storage set) internal view returns (uint256) { - return _length(set._inner); - } - - /** - * @dev Returns the value stored at position `index` in the set. O(1). - * - * Note that there are no guarantees on the ordering of values inside the - * array, and it may change when more values are added or removed. - * - * Requirements: - * - * - `index` must be strictly less than {length}. - */ - function at(UintSet storage set, uint256 index) internal view returns (uint256) { - return uint256(_at(set._inner, index)); - } - - /** - * @dev Return the entire set in an array - * - * WARNING: This operation will copy the entire storage to memory, which can be quite expensive. This is designed - * to mostly be used by view accessors that are queried without any gas fees. Developers should keep in mind that - * this function has an unbounded cost, and using it as part of a state-changing function may render the function - * uncallable if the set grows to a point where copying to memory consumes too much gas to fit in a block. - */ - function values(UintSet storage set) internal view returns (uint256[] memory) { - bytes32[] memory store = _values(set._inner); - uint256[] memory result; - - /// @solidity memory-safe-assembly - assembly { - result := store - } - - return result; - } -} - - -contract ActivityPool is Operator { - using SafeMath for uint256; - using SafeERC20 for IERC20; - using EnumerableSet for EnumerableSet.AddressSet; - using EnumerableSet for EnumerableSet.UintSet; - - event AddNewAct(uint256 id); - event Bet(address user, uint256 pID, uint256 bType, uint256 amount, uint256 time); - event SetPrize(uint256 pID, uint256 bType); - event Claim(address user, uint256 pID, uint256 bType, uint256 amount); - event RemovePeriodAct(uint256 pID); - - uint256 public constant muti = 1e18; - uint256 public periodID; - uint256 public betID; - - struct UserInfo { - address user; - uint256 pID; - uint256 amount; - uint256 betTime; - uint256 bType; - uint256 claimAmount; - } - - struct ActInfo { - string name; - string aName; - string bName; - address rewardToken; - uint256 startTime; - uint256 endTime; - uint256 minAmount; - uint256 maxAmount; - uint256 aAmount; - uint256 bAmount; - uint256 winType; - bool isBet; - } - - struct TimeInfo { - uint256 time; - uint256 aAmount; - uint256 bAmount; - } - - struct BestInfo { - address aUser; - address bUser; - uint256 aBet; - uint256 bBet; - } - - mapping(uint256 => BestInfo) bestInfo; - mapping(uint256 => uint256) public timeID; - mapping(uint256 => mapping(uint256 => TimeInfo)) public timeInfo; - mapping(address => mapping(uint256 => uint256)) public userBet; - mapping(uint256 => UserInfo) public betInfo; - mapping(uint256 => uint256) public perAmount; - mapping(uint256 => ActInfo) public actInfo; - mapping(uint256 => mapping(uint256 => string)) public descripName; - - mapping(address => EnumerableSet.UintSet) userPid; - mapping(uint256 => EnumerableSet.AddressSet) aUsers; - mapping(uint256 => EnumerableSet.AddressSet) bUsers; - EnumerableSet.UintSet activePeriod; - EnumerableSet.UintSet removePeriod; - - function addNewAct( - string memory name, - string memory aName, - string memory bName, - address token, - uint256 startTime, - uint256 endTime, - uint256 minAmount, - uint256 maxAmount - ) external onlyOperator { - - checkAdd(msg.sender, startTime, endTime, minAmount, maxAmount); - uint256 id = ++periodID; - actInfo[id].name = name; - actInfo[id].aName = aName; - actInfo[id].bName = bName; - actInfo[id].startTime = startTime; - actInfo[id].endTime = endTime; - actInfo[id].minAmount = minAmount; - actInfo[id].maxAmount = maxAmount; - actInfo[id].rewardToken = token; - descripName[id][1] = aName; - descripName[id][2] = bName; - activePeriod.add(id); - - emit AddNewAct(id); - } - - - function removePeriodAct(uint256 pID) external onlyOperator { - checkRemove(pID); - - activePeriod.remove(pID); - removePeriod.add(pID); - - emit RemovePeriodAct(pID); - } - - - function bet(uint256 pID, uint256 bType, uint256 amount) external payable { - checkBet(msg.sender, pID, bType, amount); - if(actInfo[pID].rewardToken == address(0)) { - require(msg.value == amount, "value err"); - } else { - require(msg.value == 0, "value amount err"); - } - - if(bType == 1) { - if(amount > bestInfo[pID].aBet) { - bestInfo[pID].aUser = msg.sender; - bestInfo[pID].aBet = amount; - } - } else { - if(amount > bestInfo[pID].bBet) { - bestInfo[pID].bUser = msg.sender; - bestInfo[pID].bBet = amount; - } - } - - userPid[msg.sender].add(pID); - uint256 id = ++betID; - userBet[msg.sender][pID] = id; - - if(bType == 1) { - aUsers[pID].add(msg.sender); - actInfo[pID].aAmount = actInfo[pID].aAmount.add(amount); - } else { - bUsers[pID].add(msg.sender); - actInfo[pID].bAmount = actInfo[pID].bAmount.add(amount); - } - - actInfo[pID].isBet = true; - betInfo[id].user = msg.sender; - betInfo[id].pID = pID; - betInfo[id].amount = amount; - betInfo[id].betTime = block.timestamp; - betInfo[id].bType = bType; - - uint256 tID = ++timeID[pID]; - timeInfo[pID][tID].time = block.timestamp; - timeInfo[pID][tID].aAmount = actInfo[pID].aAmount; - timeInfo[pID][tID].bAmount = actInfo[pID].bAmount; - - if(actInfo[pID].rewardToken != address(0)) { - IERC20(actInfo[pID].rewardToken).safeTransferFrom(msg.sender, address(this), amount); - } - emit Bet(msg.sender, pID, bType, amount, betInfo[id].betTime); - } - - function setPrize(uint256 pID, uint256 bType) external onlyOperator { - checkSetPrize(msg.sender, pID, bType); - - if(block.timestamp <= actInfo[pID].startTime) { - actInfo[pID].startTime = block.timestamp; - - } - actInfo[pID].endTime = block.timestamp; - - actInfo[pID].winType = bType; - perAmount[pID] = getPerAmount(pID, bType); - - emit SetPrize(pID, bType); - } - - function recive() public payable {} - - function claim(uint256 pID) external { - uint256 amount = checkClaim(msg.sender, pID); - - uint256 id = userBet[msg.sender][pID]; - betInfo[id].claimAmount = amount; - if(actInfo[pID].rewardToken != address(0)) { - IERC20(actInfo[pID].rewardToken).safeTransfer(msg.sender, amount); - } else { - payable(msg.sender).transfer(amount); - } - - emit Claim(msg.sender, pID, betInfo[id].bType, amount); - } - - function checkClaim(address user, uint256 pID) public view returns(uint256 amount) { - require(userPid[user].contains(pID), "not bet"); - uint256 id = userBet[user][pID]; - require(betInfo[id].user == user, "not user"); - require(actInfo[pID].winType != 0, "not prize"); - require(betInfo[id].claimAmount == 0, "has claim"); - - if(actInfo[pID].winType != 3) { - require(actInfo[pID].winType == betInfo[id].bType, "not right"); - amount = perAmount[pID].mul(betInfo[id].amount).div(muti); - require(amount > 0, "no amount"); - } else { - amount = betInfo[id].amount; - } - - return amount; - } - - function getActualRate( - address user, - uint256 pID, - uint256 bType, - uint256 amount - ) external view returns(uint256, uint256, bool) { - if(bType < 1 || bType > 2 || !activePeriod.contains(pID)) { - return (0, 0, false); - } else if(userBet[user][pID] != 0 || actInfo[pID].winType != 0 || amount == 0) { - (uint256 ra, uint256 rb) = getRate(pID, timeID[pID]); - return (ra, rb, false); - } else { - (uint256 aAmount, uint256 bAmount) = (actInfo[pID].aAmount, actInfo[pID].bAmount); - if(bType == 1) { - aAmount = aAmount.add(amount); - } else { - bAmount = bAmount.add(amount); - } - - uint256 total = aAmount.add(bAmount); - if(bAmount == 0 && aAmount != 0) { - return (muti, 0, true); - } - if(bAmount != 0 && aAmount == 0) { - return (0, muti, true); - } - return (total.mul(muti).div(aAmount), total.mul(muti).div(bAmount), true); - } - } - - function getRate(uint256 pID, uint256 tID) public view returns(uint256, uint256) { - (uint256 aAmount, uint256 bAmount) = (timeInfo[pID][tID].aAmount, timeInfo[pID][tID].bAmount); - uint256 total = aAmount.add(bAmount); - if(total == 0) { - return (0, 0); - } - if(bAmount == 0 && aAmount != 0) { - return (muti, 0); - } - if(bAmount != 0 && aAmount == 0) { - return (0, muti); - } - return (total.mul(muti).div(aAmount), total.mul(muti).div(bAmount)); - } - - function getBestInfo(uint256 pID) - external - view - returns(address aUser, address bUser, uint256 aBet, uint256 bBet, uint256 aReward, uint256 bReward) - { - aUser = bestInfo[pID].aUser; - bUser = bestInfo[pID].bUser; - aBet = bestInfo[pID].aBet; - bBet = bestInfo[pID].bBet; - aReward = getPerAmount(pID, 1).mul(aBet).div(muti); - bReward = getPerAmount(pID, 2).mul(bBet).div(muti); - } - - function getPerAmount(uint256 pID, uint256 bType) public view returns(uint256) { - uint256 total = actInfo[pID].aAmount.add(actInfo[pID].bAmount); - if(total == 0) { - return 0; - } - - if(actInfo[pID].winType == 3) { - return muti; - } - - if(bType == 1) { - if(actInfo[pID].aAmount == 0 || actInfo[pID].winType == 2) { - return 0; - } - return total.mul(muti).div(actInfo[pID].aAmount); - } - - if(bType == 2) { - if(actInfo[pID].bAmount == 0 || actInfo[pID].winType == 1) { - return 0; - } - return total.mul(muti).div(actInfo[pID].bAmount); - } - - return 0; - - } - - function checkSetPrize(address user, uint256 pID, uint256 bType) public view returns(bool) { - require(user == owner() || user == operator, "no permission"); - require(bType > 0 && bType <= 3, "type err"); - require(activePeriod.contains(pID), "not active"); - require(actInfo[pID].winType == 0, "has set"); - - return true; - } - - function checkBet( - address user, - uint256 pID, - uint256 bType, - uint256 amount - ) public view returns(bool) { - require(activePeriod.contains(pID), "not active"); - require(actInfo[pID].startTime <= block.timestamp, "not start"); - require(actInfo[pID].endTime > block.timestamp, "has end"); - require(!userPid[user].contains(pID), "has bet"); - require(bType > 0 && bType < 3, "type err"); - require(amount >= actInfo[pID].minAmount && amount <= actInfo[pID].maxAmount, "amount err"); - if(actInfo[pID].rewardToken != address(0)) { - require(IERC20(actInfo[pID].rewardToken).allowance(user, address(this)) >= amount, "not approve enough"); - require(IERC20(actInfo[pID].rewardToken).balanceOf(user) >= amount, "not enough"); - } else { - require(user.balance >= amount, "main token err"); - } - - return true; - } - - - function checkRemove(uint256 pID) public view returns(bool) { - require(activePeriod.contains(pID), "not in"); - require(!actInfo[pID].isBet, "has bet"); - - return true; - } - - function checkAdd( - address user, - uint256 startTime, - uint256 endTime, - uint256 minAmount, - uint256 maxAmount - ) public view returns(bool) { - require(user == owner() || user == operator, "no permission"); - require(startTime > block.timestamp, "startTime err"); - require(endTime > startTime, "endTime err"); - require(minAmount > 0 && maxAmount > minAmount, "amount err"); - - return true; - } - - function getStatus(uint256 pID) external view returns(uint256) { - if(!removePeriod.contains(pID) && !activePeriod.contains(pID)) { - return 5; - } else if(removePeriod.contains(pID)) { - return 6; - } else if(block.timestamp < actInfo[pID].startTime) { - return 1; - } else if ( - actInfo[pID].startTime <= block.timestamp && - actInfo[pID].endTime > block.timestamp - ) { - return 2; - } else if (actInfo[pID].endTime <= block.timestamp && actInfo[pID].winType == 0){ - return 3; - } else if(actInfo[pID].winType != 0) { - return 4; - } - return 0; - } - - function getUserPidNum(address user) external view returns(uint256) { - return userPid[user].length(); - } - - function getUserPid(address user, uint256 index) external view returns(uint256) { - return userPid[user].at(index); - } - - function getAUsersNum(uint256 pID) external view returns(uint256) { - return aUsers[pID].length(); - } - - function getAUsers(uint256 pID, uint256 index) external view returns(address) { - return aUsers[pID].at(index); - } - - function getBUsersNum(uint256 pID) external view returns(uint256) { - return bUsers[pID].length(); - } - - function getBUsers(uint256 pID, uint256 index) external view returns(address) { - return bUsers[pID].at(index); - } - - function getActivePeriodNum() external view returns(uint256) { - return activePeriod.length(); - } - - function getActivePeriod(uint256 index) external view returns(uint256) { - return activePeriod.at(index); - } - - function getRemovePeriodNum() external view returns(uint256) { - return removePeriod.length(); - } - - function getRemovePeriod(uint256 index) external view returns(uint256) { - return removePeriod.at(index); - } -} \ No newline at end of file diff --git a/app/api/uploads/ActivityPool-1729807762472-693738646.sol b/app/api/uploads/ActivityPool-1729807762472-693738646.sol deleted file mode 100644 index daf3372..0000000 --- a/app/api/uploads/ActivityPool-1729807762472-693738646.sol +++ /dev/null @@ -1,1648 +0,0 @@ -// SPDX-License-Identifier: MIT -// OpenZeppelin Contracts (last updated v4.7.0) (utils/Address.sol) - -pragma solidity ^0.8.1; - -/** - * @dev Collection of functions related to the address type - */ -library Address { - /** - * @dev Returns true if `account` is a contract. - * - * [IMPORTANT] - * ==== - * It is unsafe to assume that an address for which this function returns - * false is an externally-owned account (EOA) and not a contract. - * - * Among others, `isContract` will return false for the following - * types of addresses: - * - * - an externally-owned account - * - a contract in construction - * - an address where a contract will be created - * - an address where a contract lived, but was destroyed - * ==== - * - * [IMPORTANT] - * ==== - * You shouldn't rely on `isContract` to protect against flash loan attacks! - * - * Preventing calls from contracts is highly discouraged. It breaks composability, breaks support for smart wallets - * like Gnosis Safe, and does not provide security since it can be circumvented by calling from a contract - * constructor. - * ==== - */ - function isContract(address account) internal view returns (bool) { - // This method relies on extcodesize/address.code.length, which returns 0 - // for contracts in construction, since the code is only stored at the end - // of the constructor execution. - - return account.code.length > 0; - } - - /** - * @dev Replacement for Solidity's `transfer`: sends `amount` wei to - * `recipient`, forwarding all available gas and reverting on errors. - * - * https://eips.ethereum.org/EIPS/eip-1884[EIP1884] increases the gas cost - * of certain opcodes, possibly making contracts go over the 2300 gas limit - * imposed by `transfer`, making them unable to receive funds via - * `transfer`. {sendValue} removes this limitation. - * - * https://diligence.consensys.net/posts/2019/09/stop-using-soliditys-transfer-now/[Learn more]. - * - * IMPORTANT: because control is transferred to `recipient`, care must be - * taken to not create reentrancy vulnerabilities. Consider using - * {ReentrancyGuard} or the - * https://solidity.readthedocs.io/en/v0.5.11/security-considerations.html#use-the-checks-effects-interactions-pattern[checks-effects-interactions pattern]. - */ - function sendValue(address payable recipient, uint256 amount) internal { - require(address(this).balance >= amount, "Address: insufficient balance"); - - (bool success, ) = recipient.call{value: amount}(""); - require(success, "Address: unable to send value, recipient may have reverted"); - } - - /** - * @dev Performs a Solidity function call using a low level `call`. A - * plain `call` is an unsafe replacement for a function call: use this - * function instead. - * - * If `target` reverts with a revert reason, it is bubbled up by this - * function (like regular Solidity function calls). - * - * Returns the raw returned data. To convert to the expected return value, - * use https://solidity.readthedocs.io/en/latest/units-and-global-variables.html?highlight=abi.decode#abi-encoding-and-decoding-functions[`abi.decode`]. - * - * Requirements: - * - * - `target` must be a contract. - * - calling `target` with `data` must not revert. - * - * _Available since v3.1._ - */ - function functionCall(address target, bytes memory data) internal returns (bytes memory) { - return functionCallWithValue(target, data, 0, "Address: low-level call failed"); - } - - /** - * @dev Same as {xref-Address-functionCall-address-bytes-}[`functionCall`], but with - * `errorMessage` as a fallback revert reason when `target` reverts. - * - * _Available since v3.1._ - */ - function functionCall( - address target, - bytes memory data, - string memory errorMessage - ) internal returns (bytes memory) { - return functionCallWithValue(target, data, 0, errorMessage); - } - - /** - * @dev Same as {xref-Address-functionCall-address-bytes-}[`functionCall`], - * but also transferring `value` wei to `target`. - * - * Requirements: - * - * - the calling contract must have an ETH balance of at least `value`. - * - the called Solidity function must be `payable`. - * - * _Available since v3.1._ - */ - function functionCallWithValue( - address target, - bytes memory data, - uint256 value - ) internal returns (bytes memory) { - return functionCallWithValue(target, data, value, "Address: low-level call with value failed"); - } - - /** - * @dev Same as {xref-Address-functionCallWithValue-address-bytes-uint256-}[`functionCallWithValue`], but - * with `errorMessage` as a fallback revert reason when `target` reverts. - * - * _Available since v3.1._ - */ - function functionCallWithValue( - address target, - bytes memory data, - uint256 value, - string memory errorMessage - ) internal returns (bytes memory) { - require(address(this).balance >= value, "Address: insufficient balance for call"); - (bool success, bytes memory returndata) = target.call{value: value}(data); - return verifyCallResultFromTarget(target, success, returndata, errorMessage); - } - - /** - * @dev Same as {xref-Address-functionCall-address-bytes-}[`functionCall`], - * but performing a static call. - * - * _Available since v3.3._ - */ - function functionStaticCall(address target, bytes memory data) internal view returns (bytes memory) { - return functionStaticCall(target, data, "Address: low-level static call failed"); - } - - /** - * @dev Same as {xref-Address-functionCall-address-bytes-string-}[`functionCall`], - * but performing a static call. - * - * _Available since v3.3._ - */ - function functionStaticCall( - address target, - bytes memory data, - string memory errorMessage - ) internal view returns (bytes memory) { - (bool success, bytes memory returndata) = target.staticcall(data); - return verifyCallResultFromTarget(target, success, returndata, errorMessage); - } - - /** - * @dev Same as {xref-Address-functionCall-address-bytes-}[`functionCall`], - * but performing a delegate call. - * - * _Available since v3.4._ - */ - function functionDelegateCall(address target, bytes memory data) internal returns (bytes memory) { - return functionDelegateCall(target, data, "Address: low-level delegate call failed"); - } - - /** - * @dev Same as {xref-Address-functionCall-address-bytes-string-}[`functionCall`], - * but performing a delegate call. - * - * _Available since v3.4._ - */ - function functionDelegateCall( - address target, - bytes memory data, - string memory errorMessage - ) internal returns (bytes memory) { - (bool success, bytes memory returndata) = target.delegatecall(data); - return verifyCallResultFromTarget(target, success, returndata, errorMessage); - } - - /** - * @dev Tool to verify that a low level call to smart-contract was successful, and revert (either by bubbling - * the revert reason or using the provided one) in case of unsuccessful call or if target was not a contract. - * - * _Available since v4.8._ - */ - function verifyCallResultFromTarget( - address target, - bool success, - bytes memory returndata, - string memory errorMessage - ) internal view returns (bytes memory) { - if (success) { - if (returndata.length == 0) { - // only check isContract if the call was successful and the return data is empty - // otherwise we already know that it was a contract - require(isContract(target), "Address: call to non-contract"); - } - return returndata; - } else { - _revert(returndata, errorMessage); - } - } - - /** - * @dev Tool to verify that a low level call was successful, and revert if it wasn't, either by bubbling the - * revert reason or using the provided one. - * - * _Available since v4.3._ - */ - function verifyCallResult( - bool success, - bytes memory returndata, - string memory errorMessage - ) internal pure returns (bytes memory) { - if (success) { - return returndata; - } else { - _revert(returndata, errorMessage); - } - } - - function _revert(bytes memory returndata, string memory errorMessage) private pure { - // Look for revert reason and bubble it up if present - if (returndata.length > 0) { - // The easiest way to bubble the revert reason is using memory via assembly - /// @solidity memory-safe-assembly - assembly { - let returndata_size := mload(returndata) - revert(add(32, returndata), returndata_size) - } - } else { - revert(errorMessage); - } - } -} - -// OpenZeppelin Contracts (last updated v4.6.0) (token/ERC20/IERC20.sol) - - - -/** - * @dev Interface of the ERC20 standard as defined in the EIP. - */ -interface IERC20 { - /** - * @dev Emitted when `value` tokens are moved from one account (`from`) to - * another (`to`). - * - * Note that `value` may be zero. - */ - event Transfer(address indexed from, address indexed to, uint256 value); - - /** - * @dev Emitted when the allowance of a `spender` for an `owner` is set by - * a call to {approve}. `value` is the new allowance. - */ - event Approval(address indexed owner, address indexed spender, uint256 value); - - /** - * @dev Returns the amount of tokens in existence. - */ - function totalSupply() external view returns (uint256); - - /** - * @dev Returns the amount of tokens owned by `account`. - */ - function balanceOf(address account) external view returns (uint256); - - /** - * @dev Moves `amount` tokens from the caller's account to `to`. - * - * Returns a boolean value indicating whether the operation succeeded. - * - * Emits a {Transfer} event. - */ - function transfer(address to, uint256 amount) external returns (bool); - - /** - * @dev Returns the remaining number of tokens that `spender` will be - * allowed to spend on behalf of `owner` through {transferFrom}. This is - * zero by default. - * - * This value changes when {approve} or {transferFrom} are called. - */ - function allowance(address owner, address spender) external view returns (uint256); - - /** - * @dev Sets `amount` as the allowance of `spender` over the caller's tokens. - * - * Returns a boolean value indicating whether the operation succeeded. - * - * IMPORTANT: Beware that changing an allowance with this method brings the risk - * that someone may use both the old and the new allowance by unfortunate - * transaction ordering. One possible solution to mitigate this race - * condition is to first reduce the spender's allowance to 0 and set the - * desired value afterwards: - * https://github.com/ethereum/EIPs/issues/20#issuecomment-263524729 - * - * Emits an {Approval} event. - */ - function approve(address spender, uint256 amount) external returns (bool); - - /** - * @dev Moves `amount` tokens from `from` to `to` using the - * allowance mechanism. `amount` is then deducted from the caller's - * allowance. - * - * Returns a boolean value indicating whether the operation succeeded. - * - * Emits a {Transfer} event. - */ - function transferFrom( - address from, - address to, - uint256 amount - ) external returns (bool); - - - function mint(address account_, uint256 amount_) external; - - function burn(uint256 amount) external; - -} - - - - - - - - - - - -/** - * @dev Wrappers over Solidity's arithmetic operations with added overflow - * checks. - * - * Arithmetic operations in Solidity wrap on overflow. This can easily result - * in bugs, because programmers usually assume that an overflow raises an - * error, which is the standard behavior in high level programming languages. - * `SafeMath` restores this intuition by reverting the transaction when an - * operation overflows. - * - * Using this library instead of the unchecked operations eliminates an entire - * class of bugs, so it's recommended to use it always. - */ -library SafeMath { - /** - * @dev Returns the addition of two unsigned integers, reverting on - * overflow. - * - * Counterpart to Solidity's `+` operator. - * - * Requirements: - * - * - Addition cannot overflow. - */ - function add(uint256 a, uint256 b) internal pure returns (uint256) { - uint256 c = a + b; - require(c >= a, "SafeMath: addition overflow"); - - return c; - } - - /** - * @dev Returns the subtraction of two unsigned integers, reverting on - * overflow (when the result is negative). - * - * Counterpart to Solidity's `-` operator. - * - * Requirements: - * - * - Subtraction cannot overflow. - */ - function sub(uint256 a, uint256 b) internal pure returns (uint256) { - return sub(a, b, "SafeMath: subtraction overflow"); - } - - /** - * @dev Returns the subtraction of two unsigned integers, reverting with custom message on - * overflow (when the result is negative). - * - * Counterpart to Solidity's `-` operator. - * - * Requirements: - * - * - Subtraction cannot overflow. - */ - function sub( - uint256 a, - uint256 b, - string memory errorMessage - ) internal pure returns (uint256) { - require(b <= a, errorMessage); - uint256 c = a - b; - - return c; - } - - /** - * @dev Returns the multiplication of two unsigned integers, reverting on - * overflow. - * - * Counterpart to Solidity's `*` operator. - * - * Requirements: - * - * - Multiplication cannot overflow. - */ - function mul(uint256 a, uint256 b) internal pure returns (uint256) { - // Gas optimization: this is cheaper than requiring 'a' not being zero, but the - // benefit is lost if 'b' is also tested. - // See: https://github.com/OpenZeppelin/openzeppelin-contracts/pull/522 - if (a == 0) { - return 0; - } - - uint256 c = a * b; - require(c / a == b, "SafeMath: multiplication overflow"); - - return c; - } - - /** - * @dev Returns the integer division of two unsigned integers. Reverts on - * division by zero. The result is rounded towards zero. - * - * Counterpart to Solidity's `/` operator. Note: this function uses a - * `revert` opcode (which leaves remaining gas untouched) while Solidity - * uses an invalid opcode to revert (consuming all remaining gas). - * - * Requirements: - * - * - The divisor cannot be zero. - */ - function div(uint256 a, uint256 b) internal pure returns (uint256) { - return div(a, b, "SafeMath: division by zero"); - } - - /** - * @dev Returns the integer division of two unsigned integers. Reverts with custom message on - * division by zero. The result is rounded towards zero. - * - * Counterpart to Solidity's `/` operator. Note: this function uses a - * `revert` opcode (which leaves remaining gas untouched) while Solidity - * uses an invalid opcode to revert (consuming all remaining gas). - * - * Requirements: - * - * - The divisor cannot be zero. - */ - function div( - uint256 a, - uint256 b, - string memory errorMessage - ) internal pure returns (uint256) { - require(b > 0, errorMessage); - uint256 c = a / b; - // assert(a == b * c + a % b); // There is no case in which this doesn't hold - - return c; - } - - /** - * @dev Returns the remainder of dividing two unsigned integers. (unsigned integer modulo), - * Reverts when dividing by zero. - * - * Counterpart to Solidity's `%` operator. This function uses a `revert` - * opcode (which leaves remaining gas untouched) while Solidity uses an - * invalid opcode to revert (consuming all remaining gas). - * - * Requirements: - * - * - The divisor cannot be zero. - */ - function mod(uint256 a, uint256 b) internal pure returns (uint256) { - return mod(a, b, "SafeMath: modulo by zero"); - } - - /** - * @dev Returns the remainder of dividing two unsigned integers. (unsigned integer modulo), - * Reverts with custom message when dividing by zero. - * - * Counterpart to Solidity's `%` operator. This function uses a `revert` - * opcode (which leaves remaining gas untouched) while Solidity uses an - * invalid opcode to revert (consuming all remaining gas). - * - * Requirements: - * - * - The divisor cannot be zero. - */ - function mod( - uint256 a, - uint256 b, - string memory errorMessage - ) internal pure returns (uint256) { - require(b != 0, errorMessage); - return a % b; - } - - // babylonian method (https://en.wikipedia.org/wiki/Methods_of_computing_square_roots#Babylonian_method) - function sqrrt(uint256 a) internal pure returns (uint256 c) { - if (a > 3) { - c = a; - uint256 b = add(div(a, 2), 1); - while (b < c) { - c = b; - b = div(add(div(a, b), b), 2); - } - } else if (a != 0) { - c = 1; - } - } - - /* - * Expects percentage to be trailed by 00, - */ - function percentageAmount(uint256 total_, uint8 percentage_) internal pure returns (uint256 percentAmount_) { - return div(mul(total_, percentage_), 1000); - } - - /* - * Expects percentage to be trailed by 00, - */ - function substractPercentage(uint256 total_, uint8 percentageToSub_) internal pure returns (uint256 result_) { - return sub(total_, div(mul(total_, percentageToSub_), 1000)); - } - - function percentageOfTotal(uint256 part_, uint256 total_) internal pure returns (uint256 percent_) { - return div(mul(part_, 100), total_); - } - - /** - * Taken from Hypersonic https://github.com/M2629/HyperSonic/blob/main/Math.sol - * @dev Returns the average of two numbers. The result is rounded towards - * zero. - */ - function average(uint256 a, uint256 b) internal pure returns (uint256) { - // (a + b) / 2 can overflow, so we distribute - return (a / 2) + (b / 2) + (((a % 2) + (b % 2)) / 2); - } - - function quadraticPricing(uint256 payment_, uint256 multiplier_) internal pure returns (uint256) { - return sqrrt(mul(multiplier_, payment_)); - } - - function bondingCurve(uint256 supply_, uint256 multiplier_) internal pure returns (uint256) { - return mul(multiplier_, supply_); - } -} - -// OpenZeppelin Contracts (last updated v4.7.0) (token/ERC20/utils/SafeERC20.sol) - - - - - -// OpenZeppelin Contracts v4.4.1 (token/ERC20/extensions/draft-IERC20Permit.sol) - - - -/** - * @dev Interface of the ERC20 Permit extension allowing approvals to be made via signatures, as defined in - * https://eips.ethereum.org/EIPS/eip-2612[EIP-2612]. - * - * Adds the {permit} method, which can be used to change an account's ERC20 allowance (see {IERC20-allowance}) by - * presenting a message signed by the account. By not relying on {IERC20-approve}, the token holder account doesn't - * need to send a transaction, and thus is not required to hold Ether at all. - */ -interface IERC20Permit { - /** - * @dev Sets `value` as the allowance of `spender` over ``owner``'s tokens, - * given ``owner``'s signed approval. - * - * IMPORTANT: The same issues {IERC20-approve} has related to transaction - * ordering also apply here. - * - * Emits an {Approval} event. - * - * Requirements: - * - * - `spender` cannot be the zero address. - * - `deadline` must be a timestamp in the future. - * - `v`, `r` and `s` must be a valid `secp256k1` signature from `owner` - * over the EIP712-formatted function arguments. - * - the signature must use ``owner``'s current nonce (see {nonces}). - * - * For more information on the signature format, see the - * https://eips.ethereum.org/EIPS/eip-2612#specification[relevant EIP - * section]. - */ - function permit( - address owner, - address spender, - uint256 value, - uint256 deadline, - uint8 v, - bytes32 r, - bytes32 s - ) external; - - /** - * @dev Returns the current nonce for `owner`. This value must be - * included whenever a signature is generated for {permit}. - * - * Every successful call to {permit} increases ``owner``'s nonce by one. This - * prevents a signature from being used multiple times. - */ - function nonces(address owner) external view returns (uint256); - - /** - * @dev Returns the domain separator used in the encoding of the signature for {permit}, as defined by {EIP712}. - */ - // solhint-disable-next-line func-name-mixedcase - function DOMAIN_SEPARATOR() external view returns (bytes32); -} - - - -/** - * @title SafeERC20 - * @dev Wrappers around ERC20 operations that throw on failure (when the token - * contract returns false). Tokens that return no value (and instead revert or - * throw on failure) are also supported, non-reverting calls are assumed to be - * successful. - * To use this library you can add a `using SafeERC20 for IERC20;` statement to your contract, - * which allows you to call the safe operations as `token.safeTransfer(...)`, etc. - */ -library SafeERC20 { - using Address for address; - - function safeTransfer( - IERC20 token, - address to, - uint256 value - ) internal { - _callOptionalReturn(token, abi.encodeWithSelector(token.transfer.selector, to, value)); - } - - function safeTransferFrom( - IERC20 token, - address from, - address to, - uint256 value - ) internal { - _callOptionalReturn(token, abi.encodeWithSelector(token.transferFrom.selector, from, to, value)); - } - - /** - * @dev Deprecated. This function has issues similar to the ones found in - * {IERC20-approve}, and its usage is discouraged. - * - * Whenever possible, use {safeIncreaseAllowance} and - * {safeDecreaseAllowance} instead. - */ - function safeApprove( - IERC20 token, - address spender, - uint256 value - ) internal { - // safeApprove should only be called when setting an initial allowance, - // or when resetting it to zero. To increase and decrease it, use - // 'safeIncreaseAllowance' and 'safeDecreaseAllowance' - require( - (value == 0) || (token.allowance(address(this), spender) == 0), - "SafeERC20: approve from non-zero to non-zero allowance" - ); - _callOptionalReturn(token, abi.encodeWithSelector(token.approve.selector, spender, value)); - } - - function safeIncreaseAllowance( - IERC20 token, - address spender, - uint256 value - ) internal { - uint256 newAllowance = token.allowance(address(this), spender) + value; - _callOptionalReturn(token, abi.encodeWithSelector(token.approve.selector, spender, newAllowance)); - } - - function safeDecreaseAllowance( - IERC20 token, - address spender, - uint256 value - ) internal { - unchecked { - uint256 oldAllowance = token.allowance(address(this), spender); - require(oldAllowance >= value, "SafeERC20: decreased allowance below zero"); - uint256 newAllowance = oldAllowance - value; - _callOptionalReturn(token, abi.encodeWithSelector(token.approve.selector, spender, newAllowance)); - } - } - - function safePermit( - IERC20Permit token, - address owner, - address spender, - uint256 value, - uint256 deadline, - uint8 v, - bytes32 r, - bytes32 s - ) internal { - uint256 nonceBefore = token.nonces(owner); - token.permit(owner, spender, value, deadline, v, r, s); - uint256 nonceAfter = token.nonces(owner); - require(nonceAfter == nonceBefore + 1, "SafeERC20: permit did not succeed"); - } - - /** - * @dev Imitates a Solidity high-level call (i.e. a regular function call to a contract), relaxing the requirement - * on the return value: the return value is optional (but if data is returned, it must not be false). - * @param token The token targeted by the call. - * @param data The call data (encoded using abi.encode or one of its variants). - */ - function _callOptionalReturn(IERC20 token, bytes memory data) private { - // We need to perform a low level call here, to bypass Solidity's return data size checking mechanism, since - // we're implementing it ourselves. We use {Address.functionCall} to perform this call, which verifies that - // the target address contains contract code and also asserts for success in the low-level call. - - bytes memory returndata = address(token).functionCall(data, "SafeERC20: low-level call failed"); - if (returndata.length > 0) { - // Return data is optional - require(abi.decode(returndata, (bool)), "SafeERC20: ERC20 operation did not succeed"); - } - } -} - - - - - - - - - - - - - - -/** - * @dev Provides information about the current execution context, including the - * sender of the transaction and its data. While these are generally available - * via msg.sender and msg.data, they should not be accessed in such a direct - * manner, since when dealing with meta-transactions the account sending and - * paying for execution may not be the actual sender (as far as an application - * is concerned). - * - * This contract is only required for intermediate, library-like contracts. - */ -abstract contract Context { - function _msgSender() internal view virtual returns (address) { - return msg.sender; - } - - function _msgData() internal view virtual returns (bytes calldata) { - return msg.data; - } -} - - -/** - * @dev Contract module which provides a basic access control mechanism, where - * there is an account (an owner) that can be granted exclusive access to - * specific functions. - * - * By default, the owner account will be the one that deploys the contract. This - * can later be changed with {transferOwnership}. - * - * This module is used through inheritance. It will make available the modifier - * `onlyOwner`, which can be applied to your functions to restrict their use to - * the owner. - */ -abstract contract Ownable is Context { - address private _owner; - - event OwnershipTransferred(address indexed previousOwner, address indexed newOwner); - - /** - * @dev Initializes the contract setting the deployer as the initial owner. - */ - constructor() { - _transferOwnership(_msgSender()); - } - - /** - * @dev Throws if called by any account other than the owner. - */ - modifier onlyOwner() { - _checkOwner(); - _; - } - - /** - * @dev Returns the address of the current owner. - */ - function owner() public view virtual returns (address) { - return _owner; - } - - /** - * @dev Throws if the sender is not the owner. - */ - function _checkOwner() internal view virtual { - require(owner() == _msgSender(), "Ownable: caller is not the owner"); - } - - /** - * @dev Leaves the contract without owner. It will not be possible to call - * `onlyOwner` functions anymore. Can only be called by the current owner. - * - * NOTE: Renouncing ownership will leave the contract without an owner, - * thereby removing any functionality that is only available to the owner. - */ - function renounceOwnership() public virtual onlyOwner { - _transferOwnership(address(0)); - } - - /** - * @dev Transfers ownership of the contract to a new account (`newOwner`). - * Can only be called by the current owner. - */ - function transferOwnership(address newOwner) public virtual onlyOwner { - require(newOwner != address(0), "Ownable: new owner is the zero address"); - _transferOwnership(newOwner); - } - - /** - * @dev Transfers ownership of the contract to a new account (`newOwner`). - * Internal function without access restriction. - */ - function _transferOwnership(address newOwner) internal virtual { - address oldOwner = _owner; - _owner = newOwner; - emit OwnershipTransferred(oldOwner, newOwner); - } -} - - -contract Operator is Ownable { - address public operator; - uint256 constant baseRate = 10000; - - modifier onlyOperator { - require(msg.sender == owner() || msg.sender == operator, "no permission"); - _; - } - - function setOperator(address operator_) external onlyOwner { - operator = operator_; - } - - - function getCurrTime() external view returns(uint256) { - return block.timestamp; - } - - function getBlockNum() external view returns(uint256) { - return block.number; - } - -} - - - - - -/** - * @dev Library for managing - * https://en.wikipedia.org/wiki/Set_(abstract_data_type)[sets] of primitive - * types. - * - * Sets have the following properties: - * - * - Elements are added, removed, and checked for existence in constant time - * (O(1)). - * - Elements are enumerated in O(n). No guarantees are made on the ordering. - * - * ``` - * contract Example { - * // Add the library methods - * using EnumerableSet for EnumerableSet.AddressSet; - * - * // Declare a set state variable - * EnumerableSet.AddressSet private mySet; - * } - * ``` - * - * As of v3.3.0, sets of type `bytes32` (`Bytes32Set`), `address` (`AddressSet`) - * and `uint256` (`UintSet`) are supported. - * - * [WARNING] - * ==== - * Trying to delete such a structure from storage will likely result in data corruption, rendering the structure unusable. - * See https://github.com/ethereum/solidity/pull/11843[ethereum/solidity#11843] for more info. - * - * In order to clean an EnumerableSet, you can either remove all elements one by one or create a fresh instance using an array of EnumerableSet. - * ==== - */ - -library EnumerableSet { - // To implement this library for multiple types with as little code - // repetition as possible, we write it in terms of a generic Set type with - // bytes32 values. - // The Set implementation uses private functions, and user-facing - // implementations (such as AddressSet) are just wrappers around the - // underlying Set. - // This means that we can only create new EnumerableSets for types that fit - // in bytes32. - - struct Set { - // Storage of set values - bytes32[] _values; - // Position of the value in the `values` array, plus 1 because index 0 - // means a value is not in the set. - mapping(bytes32 => uint256) _indexes; - } - - /** - * @dev Add a value to a set. O(1). - * - * Returns true if the value was added to the set, that is if it was not - * already present. - */ - function _add(Set storage set, bytes32 value) private returns (bool) { - if (!_contains(set, value)) { - set._values.push(value); - // The value is stored at length-1, but we add 1 to all indexes - // and use 0 as a sentinel value - set._indexes[value] = set._values.length; - return true; - } else { - return false; - } - } - - /** - * @dev Removes a value from a set. O(1). - * - * Returns true if the value was removed from the set, that is if it was - * present. - */ - function _remove(Set storage set, bytes32 value) private returns (bool) { - // We read and store the value's index to prevent multiple reads from the same storage slot - uint256 valueIndex = set._indexes[value]; - - if (valueIndex != 0) { - // Equivalent to contains(set, value) - // To delete an element from the _values array in O(1), we swap the element to delete with the last one in - // the array, and then remove the last element (sometimes called as 'swap and pop'). - // This modifies the order of the array, as noted in {at}. - - uint256 toDeleteIndex = valueIndex - 1; - uint256 lastIndex = set._values.length - 1; - - if (lastIndex != toDeleteIndex) { - bytes32 lastValue = set._values[lastIndex]; - - // Move the last value to the index where the value to delete is - set._values[toDeleteIndex] = lastValue; - // Update the index for the moved value - set._indexes[lastValue] = valueIndex; // Replace lastValue's index to valueIndex - } - - // Delete the slot where the moved value was stored - set._values.pop(); - - // Delete the index for the deleted slot - delete set._indexes[value]; - - return true; - } else { - return false; - } - } - - /** - * @dev Returns true if the value is in the set. O(1). - */ - function _contains(Set storage set, bytes32 value) private view returns (bool) { - return set._indexes[value] != 0; - } - - /** - * @dev Returns the number of values on the set. O(1). - */ - function _length(Set storage set) private view returns (uint256) { - return set._values.length; - } - - /** - * @dev Returns the value stored at position `index` in the set. O(1). - * - * Note that there are no guarantees on the ordering of values inside the - * array, and it may change when more values are added or removed. - * - * Requirements: - * - * - `index` must be strictly less than {length}. - */ - function _at(Set storage set, uint256 index) private view returns (bytes32) { - return set._values[index]; - } - - /** - * @dev Return the entire set in an array - * - * WARNING: This operation will copy the entire storage to memory, which can be quite expensive. This is designed - * to mostly be used by view accessors that are queried without any gas fees. Developers should keep in mind that - * this function has an unbounded cost, and using it as part of a state-changing function may render the function - * uncallable if the set grows to a point where copying to memory consumes too much gas to fit in a block. - */ - function _values(Set storage set) private view returns (bytes32[] memory) { - return set._values; - } - - // Bytes32Set - - struct Bytes32Set { - Set _inner; - } - - /** - * @dev Add a value to a set. O(1). - * - * Returns true if the value was added to the set, that is if it was not - * already present. - */ - function add(Bytes32Set storage set, bytes32 value) internal returns (bool) { - return _add(set._inner, value); - } - - /** - * @dev Removes a value from a set. O(1). - * - * Returns true if the value was removed from the set, that is if it was - * present. - */ - function remove(Bytes32Set storage set, bytes32 value) internal returns (bool) { - return _remove(set._inner, value); - } - - /** - * @dev Returns true if the value is in the set. O(1). - */ - function contains(Bytes32Set storage set, bytes32 value) internal view returns (bool) { - return _contains(set._inner, value); - } - - /** - * @dev Returns the number of values in the set. O(1). - */ - function length(Bytes32Set storage set) internal view returns (uint256) { - return _length(set._inner); - } - - /** - * @dev Returns the value stored at position `index` in the set. O(1). - * - * Note that there are no guarantees on the ordering of values inside the - * array, and it may change when more values are added or removed. - * - * Requirements: - * - * - `index` must be strictly less than {length}. - */ - function at(Bytes32Set storage set, uint256 index) internal view returns (bytes32) { - return _at(set._inner, index); - } - - /** - * @dev Return the entire set in an array - * - * WARNING: This operation will copy the entire storage to memory, which can be quite expensive. This is designed - * to mostly be used by view accessors that are queried without any gas fees. Developers should keep in mind that - * this function has an unbounded cost, and using it as part of a state-changing function may render the function - * uncallable if the set grows to a point where copying to memory consumes too much gas to fit in a block. - */ - function values(Bytes32Set storage set) internal view returns (bytes32[] memory) { - return _values(set._inner); - } - - // AddressSet - - struct AddressSet { - Set _inner; - } - - /** - * @dev Add a value to a set. O(1). - * - * Returns true if the value was added to the set, that is if it was not - * already present. - */ - function add(AddressSet storage set, address value) internal returns (bool) { - return _add(set._inner, bytes32(uint256(uint160(value)))); - } - - /** - * @dev Removes a value from a set. O(1). - * - * Returns true if the value was removed from the set, that is if it was - * present. - */ - function remove(AddressSet storage set, address value) internal returns (bool) { - return _remove(set._inner, bytes32(uint256(uint160(value)))); - } - - /** - * @dev Returns true if the value is in the set. O(1). - */ - function contains(AddressSet storage set, address value) internal view returns (bool) { - return _contains(set._inner, bytes32(uint256(uint160(value)))); - } - - /** - * @dev Returns the number of values in the set. O(1). - */ - function length(AddressSet storage set) internal view returns (uint256) { - return _length(set._inner); - } - - /** - * @dev Returns the value stored at position `index` in the set. O(1). - * - * Note that there are no guarantees on the ordering of values inside the - * array, and it may change when more values are added or removed. - * - * Requirements: - * - * - `index` must be strictly less than {length}. - */ - function at(AddressSet storage set, uint256 index) internal view returns (address) { - return address(uint160(uint256(_at(set._inner, index)))); - } - - /** - * @dev Return the entire set in an array - * - * WARNING: This operation will copy the entire storage to memory, which can be quite expensive. This is designed - * to mostly be used by view accessors that are queried without any gas fees. Developers should keep in mind that - * this function has an unbounded cost, and using it as part of a state-changing function may render the function - * uncallable if the set grows to a point where copying to memory consumes too much gas to fit in a block. - */ - function values(AddressSet storage set) internal view returns (address[] memory) { - bytes32[] memory store = _values(set._inner); - address[] memory result; - - /// @solidity memory-safe-assembly - assembly { - result := store - } - - return result; - } - - // UintSet - - struct UintSet { - Set _inner; - } - - /** - * @dev Add a value to a set. O(1). - * - * Returns true if the value was added to the set, that is if it was not - * already present. - */ - function add(UintSet storage set, uint256 value) internal returns (bool) { - return _add(set._inner, bytes32(value)); - } - - /** - * @dev Removes a value from a set. O(1). - * - * Returns true if the value was removed from the set, that is if it was - * present. - */ - function remove(UintSet storage set, uint256 value) internal returns (bool) { - return _remove(set._inner, bytes32(value)); - } - - /** - * @dev Returns true if the value is in the set. O(1). - */ - function contains(UintSet storage set, uint256 value) internal view returns (bool) { - return _contains(set._inner, bytes32(value)); - } - - /** - * @dev Returns the number of values on the set. O(1). - */ - function length(UintSet storage set) internal view returns (uint256) { - return _length(set._inner); - } - - /** - * @dev Returns the value stored at position `index` in the set. O(1). - * - * Note that there are no guarantees on the ordering of values inside the - * array, and it may change when more values are added or removed. - * - * Requirements: - * - * - `index` must be strictly less than {length}. - */ - function at(UintSet storage set, uint256 index) internal view returns (uint256) { - return uint256(_at(set._inner, index)); - } - - /** - * @dev Return the entire set in an array - * - * WARNING: This operation will copy the entire storage to memory, which can be quite expensive. This is designed - * to mostly be used by view accessors that are queried without any gas fees. Developers should keep in mind that - * this function has an unbounded cost, and using it as part of a state-changing function may render the function - * uncallable if the set grows to a point where copying to memory consumes too much gas to fit in a block. - */ - function values(UintSet storage set) internal view returns (uint256[] memory) { - bytes32[] memory store = _values(set._inner); - uint256[] memory result; - - /// @solidity memory-safe-assembly - assembly { - result := store - } - - return result; - } -} - - -contract ActivityPool is Operator { - using SafeMath for uint256; - using SafeERC20 for IERC20; - using EnumerableSet for EnumerableSet.AddressSet; - using EnumerableSet for EnumerableSet.UintSet; - - event AddNewAct(uint256 id); - event Bet(address user, uint256 pID, uint256 bType, uint256 amount, uint256 time); - event SetPrize(uint256 pID, uint256 bType); - event Claim(address user, uint256 pID, uint256 bType, uint256 amount); - event RemovePeriodAct(uint256 pID); - - uint256 public constant muti = 1e18; - uint256 public periodID; - uint256 public betID; - - struct UserInfo { - address user; - uint256 pID; - uint256 amount; - uint256 betTime; - uint256 bType; - uint256 claimAmount; - } - - struct ActInfo { - string name; - string aName; - string bName; - address rewardToken; - uint256 startTime; - uint256 endTime; - uint256 minAmount; - uint256 maxAmount; - uint256 aAmount; - uint256 bAmount; - uint256 winType; - bool isBet; - } - - struct TimeInfo { - uint256 time; - uint256 aAmount; - uint256 bAmount; - } - - struct BestInfo { - address aUser; - address bUser; - uint256 aBet; - uint256 bBet; - } - - mapping(uint256 => BestInfo) bestInfo; - mapping(uint256 => uint256) public timeID; - mapping(uint256 => mapping(uint256 => TimeInfo)) public timeInfo; - mapping(address => mapping(uint256 => uint256)) public userBet; - mapping(uint256 => UserInfo) public betInfo; - mapping(uint256 => uint256) public perAmount; - mapping(uint256 => ActInfo) public actInfo; - mapping(uint256 => mapping(uint256 => string)) public descripName; - - mapping(address => EnumerableSet.UintSet) userPid; - mapping(uint256 => EnumerableSet.AddressSet) aUsers; - mapping(uint256 => EnumerableSet.AddressSet) bUsers; - EnumerableSet.UintSet activePeriod; - EnumerableSet.UintSet removePeriod; - - function addNewAct( - string memory name, - string memory aName, - string memory bName, - address token, - uint256 startTime, - uint256 endTime, - uint256 minAmount, - uint256 maxAmount - ) external onlyOperator { - - checkAdd(msg.sender, startTime, endTime, minAmount, maxAmount); - uint256 id = ++periodID; - actInfo[id].name = name; - actInfo[id].aName = aName; - actInfo[id].bName = bName; - actInfo[id].startTime = startTime; - actInfo[id].endTime = endTime; - actInfo[id].minAmount = minAmount; - actInfo[id].maxAmount = maxAmount; - actInfo[id].rewardToken = token; - descripName[id][1] = aName; - descripName[id][2] = bName; - activePeriod.add(id); - - emit AddNewAct(id); - } - - - function removePeriodAct(uint256 pID) external onlyOperator { - checkRemove(pID); - - activePeriod.remove(pID); - removePeriod.add(pID); - - emit RemovePeriodAct(pID); - } - - - function bet(uint256 pID, uint256 bType, uint256 amount) external payable { - checkBet(msg.sender, pID, bType, amount); - if(actInfo[pID].rewardToken == address(0)) { - require(msg.value == amount, "value err"); - } else { - require(msg.value == 0, "value amount err"); - } - - if(bType == 1) { - if(amount > bestInfo[pID].aBet) { - bestInfo[pID].aUser = msg.sender; - bestInfo[pID].aBet = amount; - } - } else { - if(amount > bestInfo[pID].bBet) { - bestInfo[pID].bUser = msg.sender; - bestInfo[pID].bBet = amount; - } - } - - userPid[msg.sender].add(pID); - uint256 id = ++betID; - userBet[msg.sender][pID] = id; - - if(bType == 1) { - aUsers[pID].add(msg.sender); - actInfo[pID].aAmount = actInfo[pID].aAmount.add(amount); - } else { - bUsers[pID].add(msg.sender); - actInfo[pID].bAmount = actInfo[pID].bAmount.add(amount); - } - - actInfo[pID].isBet = true; - betInfo[id].user = msg.sender; - betInfo[id].pID = pID; - betInfo[id].amount = amount; - betInfo[id].betTime = block.timestamp; - betInfo[id].bType = bType; - - uint256 tID = ++timeID[pID]; - timeInfo[pID][tID].time = block.timestamp; - timeInfo[pID][tID].aAmount = actInfo[pID].aAmount; - timeInfo[pID][tID].bAmount = actInfo[pID].bAmount; - - if(actInfo[pID].rewardToken != address(0)) { - IERC20(actInfo[pID].rewardToken).safeTransferFrom(msg.sender, address(this), amount); - } - emit Bet(msg.sender, pID, bType, amount, betInfo[id].betTime); - } - - function setPrize(uint256 pID, uint256 bType) external onlyOperator { - checkSetPrize(msg.sender, pID, bType); - - if(block.timestamp <= actInfo[pID].startTime) { - actInfo[pID].startTime = block.timestamp; - - } - actInfo[pID].endTime = block.timestamp; - - actInfo[pID].winType = bType; - perAmount[pID] = getPerAmount(pID, bType); - - emit SetPrize(pID, bType); - } - - function recive() public payable {} - - function claim(uint256 pID) external { - uint256 amount = checkClaim(msg.sender, pID); - - uint256 id = userBet[msg.sender][pID]; - betInfo[id].claimAmount = amount; - if(actInfo[pID].rewardToken != address(0)) { - IERC20(actInfo[pID].rewardToken).safeTransfer(msg.sender, amount); - } else { - payable(msg.sender).transfer(amount); - } - - emit Claim(msg.sender, pID, betInfo[id].bType, amount); - } - - function checkClaim(address user, uint256 pID) public view returns(uint256 amount) { - require(userPid[user].contains(pID), "not bet"); - uint256 id = userBet[user][pID]; - require(betInfo[id].user == user, "not user"); - require(actInfo[pID].winType != 0, "not prize"); - require(betInfo[id].claimAmount == 0, "has claim"); - - if(actInfo[pID].winType != 3) { - require(actInfo[pID].winType == betInfo[id].bType, "not right"); - amount = perAmount[pID].mul(betInfo[id].amount).div(muti); - require(amount > 0, "no amount"); - } else { - amount = betInfo[id].amount; - } - - return amount; - } - - function getActualRate( - address user, - uint256 pID, - uint256 bType, - uint256 amount - ) external view returns(uint256, uint256, bool) { - if(bType < 1 || bType > 2 || !activePeriod.contains(pID)) { - return (0, 0, false); - } else if(userBet[user][pID] != 0 || actInfo[pID].winType != 0 || amount == 0) { - (uint256 ra, uint256 rb) = getRate(pID, timeID[pID]); - return (ra, rb, false); - } else { - (uint256 aAmount, uint256 bAmount) = (actInfo[pID].aAmount, actInfo[pID].bAmount); - if(bType == 1) { - aAmount = aAmount.add(amount); - } else { - bAmount = bAmount.add(amount); - } - - uint256 total = aAmount.add(bAmount); - if(bAmount == 0 && aAmount != 0) { - return (muti, 0, true); - } - if(bAmount != 0 && aAmount == 0) { - return (0, muti, true); - } - return (total.mul(muti).div(aAmount), total.mul(muti).div(bAmount), true); - } - } - - function getRate(uint256 pID, uint256 tID) public view returns(uint256, uint256) { - (uint256 aAmount, uint256 bAmount) = (timeInfo[pID][tID].aAmount, timeInfo[pID][tID].bAmount); - uint256 total = aAmount.add(bAmount); - if(total == 0) { - return (0, 0); - } - if(bAmount == 0 && aAmount != 0) { - return (muti, 0); - } - if(bAmount != 0 && aAmount == 0) { - return (0, muti); - } - return (total.mul(muti).div(aAmount), total.mul(muti).div(bAmount)); - } - - function getBestInfo(uint256 pID) - external - view - returns(address aUser, address bUser, uint256 aBet, uint256 bBet, uint256 aReward, uint256 bReward) - { - aUser = bestInfo[pID].aUser; - bUser = bestInfo[pID].bUser; - aBet = bestInfo[pID].aBet; - bBet = bestInfo[pID].bBet; - aReward = getPerAmount(pID, 1).mul(aBet).div(muti); - bReward = getPerAmount(pID, 2).mul(bBet).div(muti); - } - - function getPerAmount(uint256 pID, uint256 bType) public view returns(uint256) { - uint256 total = actInfo[pID].aAmount.add(actInfo[pID].bAmount); - if(total == 0) { - return 0; - } - - if(actInfo[pID].winType == 3) { - return muti; - } - - if(bType == 1) { - if(actInfo[pID].aAmount == 0 || actInfo[pID].winType == 2) { - return 0; - } - return total.mul(muti).div(actInfo[pID].aAmount); - } - - if(bType == 2) { - if(actInfo[pID].bAmount == 0 || actInfo[pID].winType == 1) { - return 0; - } - return total.mul(muti).div(actInfo[pID].bAmount); - } - - return 0; - - } - - function checkSetPrize(address user, uint256 pID, uint256 bType) public view returns(bool) { - require(user == owner() || user == operator, "no permission"); - require(bType > 0 && bType <= 3, "type err"); - require(activePeriod.contains(pID), "not active"); - require(actInfo[pID].winType == 0, "has set"); - - return true; - } - - function checkBet( - address user, - uint256 pID, - uint256 bType, - uint256 amount - ) public view returns(bool) { - require(activePeriod.contains(pID), "not active"); - require(actInfo[pID].startTime <= block.timestamp, "not start"); - require(actInfo[pID].endTime > block.timestamp, "has end"); - require(!userPid[user].contains(pID), "has bet"); - require(bType > 0 && bType < 3, "type err"); - require(amount >= actInfo[pID].minAmount && amount <= actInfo[pID].maxAmount, "amount err"); - if(actInfo[pID].rewardToken != address(0)) { - require(IERC20(actInfo[pID].rewardToken).allowance(user, address(this)) >= amount, "not approve enough"); - require(IERC20(actInfo[pID].rewardToken).balanceOf(user) >= amount, "not enough"); - } else { - require(user.balance >= amount, "main token err"); - } - - return true; - } - - - function checkRemove(uint256 pID) public view returns(bool) { - require(activePeriod.contains(pID), "not in"); - require(!actInfo[pID].isBet, "has bet"); - - return true; - } - - function checkAdd( - address user, - uint256 startTime, - uint256 endTime, - uint256 minAmount, - uint256 maxAmount - ) public view returns(bool) { - require(user == owner() || user == operator, "no permission"); - require(startTime > block.timestamp, "startTime err"); - require(endTime > startTime, "endTime err"); - require(minAmount > 0 && maxAmount > minAmount, "amount err"); - - return true; - } - - function getStatus(uint256 pID) external view returns(uint256) { - if(!removePeriod.contains(pID) && !activePeriod.contains(pID)) { - return 5; - } else if(removePeriod.contains(pID)) { - return 6; - } else if(block.timestamp < actInfo[pID].startTime) { - return 1; - } else if ( - actInfo[pID].startTime <= block.timestamp && - actInfo[pID].endTime > block.timestamp - ) { - return 2; - } else if (actInfo[pID].endTime <= block.timestamp && actInfo[pID].winType == 0){ - return 3; - } else if(actInfo[pID].winType != 0) { - return 4; - } - return 0; - } - - function getUserPidNum(address user) external view returns(uint256) { - return userPid[user].length(); - } - - function getUserPid(address user, uint256 index) external view returns(uint256) { - return userPid[user].at(index); - } - - function getAUsersNum(uint256 pID) external view returns(uint256) { - return aUsers[pID].length(); - } - - function getAUsers(uint256 pID, uint256 index) external view returns(address) { - return aUsers[pID].at(index); - } - - function getBUsersNum(uint256 pID) external view returns(uint256) { - return bUsers[pID].length(); - } - - function getBUsers(uint256 pID, uint256 index) external view returns(address) { - return bUsers[pID].at(index); - } - - function getActivePeriodNum() external view returns(uint256) { - return activePeriod.length(); - } - - function getActivePeriod(uint256 index) external view returns(uint256) { - return activePeriod.at(index); - } - - function getRemovePeriodNum() external view returns(uint256) { - return removePeriod.length(); - } - - function getRemovePeriod(uint256 index) external view returns(uint256) { - return removePeriod.at(index); - } -} \ No newline at end of file diff --git a/app/api/uploads/ActivityPool-1729808024413-309876997.sol b/app/api/uploads/ActivityPool-1729808024413-309876997.sol deleted file mode 100644 index daf3372..0000000 --- a/app/api/uploads/ActivityPool-1729808024413-309876997.sol +++ /dev/null @@ -1,1648 +0,0 @@ -// SPDX-License-Identifier: MIT -// OpenZeppelin Contracts (last updated v4.7.0) (utils/Address.sol) - -pragma solidity ^0.8.1; - -/** - * @dev Collection of functions related to the address type - */ -library Address { - /** - * @dev Returns true if `account` is a contract. - * - * [IMPORTANT] - * ==== - * It is unsafe to assume that an address for which this function returns - * false is an externally-owned account (EOA) and not a contract. - * - * Among others, `isContract` will return false for the following - * types of addresses: - * - * - an externally-owned account - * - a contract in construction - * - an address where a contract will be created - * - an address where a contract lived, but was destroyed - * ==== - * - * [IMPORTANT] - * ==== - * You shouldn't rely on `isContract` to protect against flash loan attacks! - * - * Preventing calls from contracts is highly discouraged. It breaks composability, breaks support for smart wallets - * like Gnosis Safe, and does not provide security since it can be circumvented by calling from a contract - * constructor. - * ==== - */ - function isContract(address account) internal view returns (bool) { - // This method relies on extcodesize/address.code.length, which returns 0 - // for contracts in construction, since the code is only stored at the end - // of the constructor execution. - - return account.code.length > 0; - } - - /** - * @dev Replacement for Solidity's `transfer`: sends `amount` wei to - * `recipient`, forwarding all available gas and reverting on errors. - * - * https://eips.ethereum.org/EIPS/eip-1884[EIP1884] increases the gas cost - * of certain opcodes, possibly making contracts go over the 2300 gas limit - * imposed by `transfer`, making them unable to receive funds via - * `transfer`. {sendValue} removes this limitation. - * - * https://diligence.consensys.net/posts/2019/09/stop-using-soliditys-transfer-now/[Learn more]. - * - * IMPORTANT: because control is transferred to `recipient`, care must be - * taken to not create reentrancy vulnerabilities. Consider using - * {ReentrancyGuard} or the - * https://solidity.readthedocs.io/en/v0.5.11/security-considerations.html#use-the-checks-effects-interactions-pattern[checks-effects-interactions pattern]. - */ - function sendValue(address payable recipient, uint256 amount) internal { - require(address(this).balance >= amount, "Address: insufficient balance"); - - (bool success, ) = recipient.call{value: amount}(""); - require(success, "Address: unable to send value, recipient may have reverted"); - } - - /** - * @dev Performs a Solidity function call using a low level `call`. A - * plain `call` is an unsafe replacement for a function call: use this - * function instead. - * - * If `target` reverts with a revert reason, it is bubbled up by this - * function (like regular Solidity function calls). - * - * Returns the raw returned data. To convert to the expected return value, - * use https://solidity.readthedocs.io/en/latest/units-and-global-variables.html?highlight=abi.decode#abi-encoding-and-decoding-functions[`abi.decode`]. - * - * Requirements: - * - * - `target` must be a contract. - * - calling `target` with `data` must not revert. - * - * _Available since v3.1._ - */ - function functionCall(address target, bytes memory data) internal returns (bytes memory) { - return functionCallWithValue(target, data, 0, "Address: low-level call failed"); - } - - /** - * @dev Same as {xref-Address-functionCall-address-bytes-}[`functionCall`], but with - * `errorMessage` as a fallback revert reason when `target` reverts. - * - * _Available since v3.1._ - */ - function functionCall( - address target, - bytes memory data, - string memory errorMessage - ) internal returns (bytes memory) { - return functionCallWithValue(target, data, 0, errorMessage); - } - - /** - * @dev Same as {xref-Address-functionCall-address-bytes-}[`functionCall`], - * but also transferring `value` wei to `target`. - * - * Requirements: - * - * - the calling contract must have an ETH balance of at least `value`. - * - the called Solidity function must be `payable`. - * - * _Available since v3.1._ - */ - function functionCallWithValue( - address target, - bytes memory data, - uint256 value - ) internal returns (bytes memory) { - return functionCallWithValue(target, data, value, "Address: low-level call with value failed"); - } - - /** - * @dev Same as {xref-Address-functionCallWithValue-address-bytes-uint256-}[`functionCallWithValue`], but - * with `errorMessage` as a fallback revert reason when `target` reverts. - * - * _Available since v3.1._ - */ - function functionCallWithValue( - address target, - bytes memory data, - uint256 value, - string memory errorMessage - ) internal returns (bytes memory) { - require(address(this).balance >= value, "Address: insufficient balance for call"); - (bool success, bytes memory returndata) = target.call{value: value}(data); - return verifyCallResultFromTarget(target, success, returndata, errorMessage); - } - - /** - * @dev Same as {xref-Address-functionCall-address-bytes-}[`functionCall`], - * but performing a static call. - * - * _Available since v3.3._ - */ - function functionStaticCall(address target, bytes memory data) internal view returns (bytes memory) { - return functionStaticCall(target, data, "Address: low-level static call failed"); - } - - /** - * @dev Same as {xref-Address-functionCall-address-bytes-string-}[`functionCall`], - * but performing a static call. - * - * _Available since v3.3._ - */ - function functionStaticCall( - address target, - bytes memory data, - string memory errorMessage - ) internal view returns (bytes memory) { - (bool success, bytes memory returndata) = target.staticcall(data); - return verifyCallResultFromTarget(target, success, returndata, errorMessage); - } - - /** - * @dev Same as {xref-Address-functionCall-address-bytes-}[`functionCall`], - * but performing a delegate call. - * - * _Available since v3.4._ - */ - function functionDelegateCall(address target, bytes memory data) internal returns (bytes memory) { - return functionDelegateCall(target, data, "Address: low-level delegate call failed"); - } - - /** - * @dev Same as {xref-Address-functionCall-address-bytes-string-}[`functionCall`], - * but performing a delegate call. - * - * _Available since v3.4._ - */ - function functionDelegateCall( - address target, - bytes memory data, - string memory errorMessage - ) internal returns (bytes memory) { - (bool success, bytes memory returndata) = target.delegatecall(data); - return verifyCallResultFromTarget(target, success, returndata, errorMessage); - } - - /** - * @dev Tool to verify that a low level call to smart-contract was successful, and revert (either by bubbling - * the revert reason or using the provided one) in case of unsuccessful call or if target was not a contract. - * - * _Available since v4.8._ - */ - function verifyCallResultFromTarget( - address target, - bool success, - bytes memory returndata, - string memory errorMessage - ) internal view returns (bytes memory) { - if (success) { - if (returndata.length == 0) { - // only check isContract if the call was successful and the return data is empty - // otherwise we already know that it was a contract - require(isContract(target), "Address: call to non-contract"); - } - return returndata; - } else { - _revert(returndata, errorMessage); - } - } - - /** - * @dev Tool to verify that a low level call was successful, and revert if it wasn't, either by bubbling the - * revert reason or using the provided one. - * - * _Available since v4.3._ - */ - function verifyCallResult( - bool success, - bytes memory returndata, - string memory errorMessage - ) internal pure returns (bytes memory) { - if (success) { - return returndata; - } else { - _revert(returndata, errorMessage); - } - } - - function _revert(bytes memory returndata, string memory errorMessage) private pure { - // Look for revert reason and bubble it up if present - if (returndata.length > 0) { - // The easiest way to bubble the revert reason is using memory via assembly - /// @solidity memory-safe-assembly - assembly { - let returndata_size := mload(returndata) - revert(add(32, returndata), returndata_size) - } - } else { - revert(errorMessage); - } - } -} - -// OpenZeppelin Contracts (last updated v4.6.0) (token/ERC20/IERC20.sol) - - - -/** - * @dev Interface of the ERC20 standard as defined in the EIP. - */ -interface IERC20 { - /** - * @dev Emitted when `value` tokens are moved from one account (`from`) to - * another (`to`). - * - * Note that `value` may be zero. - */ - event Transfer(address indexed from, address indexed to, uint256 value); - - /** - * @dev Emitted when the allowance of a `spender` for an `owner` is set by - * a call to {approve}. `value` is the new allowance. - */ - event Approval(address indexed owner, address indexed spender, uint256 value); - - /** - * @dev Returns the amount of tokens in existence. - */ - function totalSupply() external view returns (uint256); - - /** - * @dev Returns the amount of tokens owned by `account`. - */ - function balanceOf(address account) external view returns (uint256); - - /** - * @dev Moves `amount` tokens from the caller's account to `to`. - * - * Returns a boolean value indicating whether the operation succeeded. - * - * Emits a {Transfer} event. - */ - function transfer(address to, uint256 amount) external returns (bool); - - /** - * @dev Returns the remaining number of tokens that `spender` will be - * allowed to spend on behalf of `owner` through {transferFrom}. This is - * zero by default. - * - * This value changes when {approve} or {transferFrom} are called. - */ - function allowance(address owner, address spender) external view returns (uint256); - - /** - * @dev Sets `amount` as the allowance of `spender` over the caller's tokens. - * - * Returns a boolean value indicating whether the operation succeeded. - * - * IMPORTANT: Beware that changing an allowance with this method brings the risk - * that someone may use both the old and the new allowance by unfortunate - * transaction ordering. One possible solution to mitigate this race - * condition is to first reduce the spender's allowance to 0 and set the - * desired value afterwards: - * https://github.com/ethereum/EIPs/issues/20#issuecomment-263524729 - * - * Emits an {Approval} event. - */ - function approve(address spender, uint256 amount) external returns (bool); - - /** - * @dev Moves `amount` tokens from `from` to `to` using the - * allowance mechanism. `amount` is then deducted from the caller's - * allowance. - * - * Returns a boolean value indicating whether the operation succeeded. - * - * Emits a {Transfer} event. - */ - function transferFrom( - address from, - address to, - uint256 amount - ) external returns (bool); - - - function mint(address account_, uint256 amount_) external; - - function burn(uint256 amount) external; - -} - - - - - - - - - - - -/** - * @dev Wrappers over Solidity's arithmetic operations with added overflow - * checks. - * - * Arithmetic operations in Solidity wrap on overflow. This can easily result - * in bugs, because programmers usually assume that an overflow raises an - * error, which is the standard behavior in high level programming languages. - * `SafeMath` restores this intuition by reverting the transaction when an - * operation overflows. - * - * Using this library instead of the unchecked operations eliminates an entire - * class of bugs, so it's recommended to use it always. - */ -library SafeMath { - /** - * @dev Returns the addition of two unsigned integers, reverting on - * overflow. - * - * Counterpart to Solidity's `+` operator. - * - * Requirements: - * - * - Addition cannot overflow. - */ - function add(uint256 a, uint256 b) internal pure returns (uint256) { - uint256 c = a + b; - require(c >= a, "SafeMath: addition overflow"); - - return c; - } - - /** - * @dev Returns the subtraction of two unsigned integers, reverting on - * overflow (when the result is negative). - * - * Counterpart to Solidity's `-` operator. - * - * Requirements: - * - * - Subtraction cannot overflow. - */ - function sub(uint256 a, uint256 b) internal pure returns (uint256) { - return sub(a, b, "SafeMath: subtraction overflow"); - } - - /** - * @dev Returns the subtraction of two unsigned integers, reverting with custom message on - * overflow (when the result is negative). - * - * Counterpart to Solidity's `-` operator. - * - * Requirements: - * - * - Subtraction cannot overflow. - */ - function sub( - uint256 a, - uint256 b, - string memory errorMessage - ) internal pure returns (uint256) { - require(b <= a, errorMessage); - uint256 c = a - b; - - return c; - } - - /** - * @dev Returns the multiplication of two unsigned integers, reverting on - * overflow. - * - * Counterpart to Solidity's `*` operator. - * - * Requirements: - * - * - Multiplication cannot overflow. - */ - function mul(uint256 a, uint256 b) internal pure returns (uint256) { - // Gas optimization: this is cheaper than requiring 'a' not being zero, but the - // benefit is lost if 'b' is also tested. - // See: https://github.com/OpenZeppelin/openzeppelin-contracts/pull/522 - if (a == 0) { - return 0; - } - - uint256 c = a * b; - require(c / a == b, "SafeMath: multiplication overflow"); - - return c; - } - - /** - * @dev Returns the integer division of two unsigned integers. Reverts on - * division by zero. The result is rounded towards zero. - * - * Counterpart to Solidity's `/` operator. Note: this function uses a - * `revert` opcode (which leaves remaining gas untouched) while Solidity - * uses an invalid opcode to revert (consuming all remaining gas). - * - * Requirements: - * - * - The divisor cannot be zero. - */ - function div(uint256 a, uint256 b) internal pure returns (uint256) { - return div(a, b, "SafeMath: division by zero"); - } - - /** - * @dev Returns the integer division of two unsigned integers. Reverts with custom message on - * division by zero. The result is rounded towards zero. - * - * Counterpart to Solidity's `/` operator. Note: this function uses a - * `revert` opcode (which leaves remaining gas untouched) while Solidity - * uses an invalid opcode to revert (consuming all remaining gas). - * - * Requirements: - * - * - The divisor cannot be zero. - */ - function div( - uint256 a, - uint256 b, - string memory errorMessage - ) internal pure returns (uint256) { - require(b > 0, errorMessage); - uint256 c = a / b; - // assert(a == b * c + a % b); // There is no case in which this doesn't hold - - return c; - } - - /** - * @dev Returns the remainder of dividing two unsigned integers. (unsigned integer modulo), - * Reverts when dividing by zero. - * - * Counterpart to Solidity's `%` operator. This function uses a `revert` - * opcode (which leaves remaining gas untouched) while Solidity uses an - * invalid opcode to revert (consuming all remaining gas). - * - * Requirements: - * - * - The divisor cannot be zero. - */ - function mod(uint256 a, uint256 b) internal pure returns (uint256) { - return mod(a, b, "SafeMath: modulo by zero"); - } - - /** - * @dev Returns the remainder of dividing two unsigned integers. (unsigned integer modulo), - * Reverts with custom message when dividing by zero. - * - * Counterpart to Solidity's `%` operator. This function uses a `revert` - * opcode (which leaves remaining gas untouched) while Solidity uses an - * invalid opcode to revert (consuming all remaining gas). - * - * Requirements: - * - * - The divisor cannot be zero. - */ - function mod( - uint256 a, - uint256 b, - string memory errorMessage - ) internal pure returns (uint256) { - require(b != 0, errorMessage); - return a % b; - } - - // babylonian method (https://en.wikipedia.org/wiki/Methods_of_computing_square_roots#Babylonian_method) - function sqrrt(uint256 a) internal pure returns (uint256 c) { - if (a > 3) { - c = a; - uint256 b = add(div(a, 2), 1); - while (b < c) { - c = b; - b = div(add(div(a, b), b), 2); - } - } else if (a != 0) { - c = 1; - } - } - - /* - * Expects percentage to be trailed by 00, - */ - function percentageAmount(uint256 total_, uint8 percentage_) internal pure returns (uint256 percentAmount_) { - return div(mul(total_, percentage_), 1000); - } - - /* - * Expects percentage to be trailed by 00, - */ - function substractPercentage(uint256 total_, uint8 percentageToSub_) internal pure returns (uint256 result_) { - return sub(total_, div(mul(total_, percentageToSub_), 1000)); - } - - function percentageOfTotal(uint256 part_, uint256 total_) internal pure returns (uint256 percent_) { - return div(mul(part_, 100), total_); - } - - /** - * Taken from Hypersonic https://github.com/M2629/HyperSonic/blob/main/Math.sol - * @dev Returns the average of two numbers. The result is rounded towards - * zero. - */ - function average(uint256 a, uint256 b) internal pure returns (uint256) { - // (a + b) / 2 can overflow, so we distribute - return (a / 2) + (b / 2) + (((a % 2) + (b % 2)) / 2); - } - - function quadraticPricing(uint256 payment_, uint256 multiplier_) internal pure returns (uint256) { - return sqrrt(mul(multiplier_, payment_)); - } - - function bondingCurve(uint256 supply_, uint256 multiplier_) internal pure returns (uint256) { - return mul(multiplier_, supply_); - } -} - -// OpenZeppelin Contracts (last updated v4.7.0) (token/ERC20/utils/SafeERC20.sol) - - - - - -// OpenZeppelin Contracts v4.4.1 (token/ERC20/extensions/draft-IERC20Permit.sol) - - - -/** - * @dev Interface of the ERC20 Permit extension allowing approvals to be made via signatures, as defined in - * https://eips.ethereum.org/EIPS/eip-2612[EIP-2612]. - * - * Adds the {permit} method, which can be used to change an account's ERC20 allowance (see {IERC20-allowance}) by - * presenting a message signed by the account. By not relying on {IERC20-approve}, the token holder account doesn't - * need to send a transaction, and thus is not required to hold Ether at all. - */ -interface IERC20Permit { - /** - * @dev Sets `value` as the allowance of `spender` over ``owner``'s tokens, - * given ``owner``'s signed approval. - * - * IMPORTANT: The same issues {IERC20-approve} has related to transaction - * ordering also apply here. - * - * Emits an {Approval} event. - * - * Requirements: - * - * - `spender` cannot be the zero address. - * - `deadline` must be a timestamp in the future. - * - `v`, `r` and `s` must be a valid `secp256k1` signature from `owner` - * over the EIP712-formatted function arguments. - * - the signature must use ``owner``'s current nonce (see {nonces}). - * - * For more information on the signature format, see the - * https://eips.ethereum.org/EIPS/eip-2612#specification[relevant EIP - * section]. - */ - function permit( - address owner, - address spender, - uint256 value, - uint256 deadline, - uint8 v, - bytes32 r, - bytes32 s - ) external; - - /** - * @dev Returns the current nonce for `owner`. This value must be - * included whenever a signature is generated for {permit}. - * - * Every successful call to {permit} increases ``owner``'s nonce by one. This - * prevents a signature from being used multiple times. - */ - function nonces(address owner) external view returns (uint256); - - /** - * @dev Returns the domain separator used in the encoding of the signature for {permit}, as defined by {EIP712}. - */ - // solhint-disable-next-line func-name-mixedcase - function DOMAIN_SEPARATOR() external view returns (bytes32); -} - - - -/** - * @title SafeERC20 - * @dev Wrappers around ERC20 operations that throw on failure (when the token - * contract returns false). Tokens that return no value (and instead revert or - * throw on failure) are also supported, non-reverting calls are assumed to be - * successful. - * To use this library you can add a `using SafeERC20 for IERC20;` statement to your contract, - * which allows you to call the safe operations as `token.safeTransfer(...)`, etc. - */ -library SafeERC20 { - using Address for address; - - function safeTransfer( - IERC20 token, - address to, - uint256 value - ) internal { - _callOptionalReturn(token, abi.encodeWithSelector(token.transfer.selector, to, value)); - } - - function safeTransferFrom( - IERC20 token, - address from, - address to, - uint256 value - ) internal { - _callOptionalReturn(token, abi.encodeWithSelector(token.transferFrom.selector, from, to, value)); - } - - /** - * @dev Deprecated. This function has issues similar to the ones found in - * {IERC20-approve}, and its usage is discouraged. - * - * Whenever possible, use {safeIncreaseAllowance} and - * {safeDecreaseAllowance} instead. - */ - function safeApprove( - IERC20 token, - address spender, - uint256 value - ) internal { - // safeApprove should only be called when setting an initial allowance, - // or when resetting it to zero. To increase and decrease it, use - // 'safeIncreaseAllowance' and 'safeDecreaseAllowance' - require( - (value == 0) || (token.allowance(address(this), spender) == 0), - "SafeERC20: approve from non-zero to non-zero allowance" - ); - _callOptionalReturn(token, abi.encodeWithSelector(token.approve.selector, spender, value)); - } - - function safeIncreaseAllowance( - IERC20 token, - address spender, - uint256 value - ) internal { - uint256 newAllowance = token.allowance(address(this), spender) + value; - _callOptionalReturn(token, abi.encodeWithSelector(token.approve.selector, spender, newAllowance)); - } - - function safeDecreaseAllowance( - IERC20 token, - address spender, - uint256 value - ) internal { - unchecked { - uint256 oldAllowance = token.allowance(address(this), spender); - require(oldAllowance >= value, "SafeERC20: decreased allowance below zero"); - uint256 newAllowance = oldAllowance - value; - _callOptionalReturn(token, abi.encodeWithSelector(token.approve.selector, spender, newAllowance)); - } - } - - function safePermit( - IERC20Permit token, - address owner, - address spender, - uint256 value, - uint256 deadline, - uint8 v, - bytes32 r, - bytes32 s - ) internal { - uint256 nonceBefore = token.nonces(owner); - token.permit(owner, spender, value, deadline, v, r, s); - uint256 nonceAfter = token.nonces(owner); - require(nonceAfter == nonceBefore + 1, "SafeERC20: permit did not succeed"); - } - - /** - * @dev Imitates a Solidity high-level call (i.e. a regular function call to a contract), relaxing the requirement - * on the return value: the return value is optional (but if data is returned, it must not be false). - * @param token The token targeted by the call. - * @param data The call data (encoded using abi.encode or one of its variants). - */ - function _callOptionalReturn(IERC20 token, bytes memory data) private { - // We need to perform a low level call here, to bypass Solidity's return data size checking mechanism, since - // we're implementing it ourselves. We use {Address.functionCall} to perform this call, which verifies that - // the target address contains contract code and also asserts for success in the low-level call. - - bytes memory returndata = address(token).functionCall(data, "SafeERC20: low-level call failed"); - if (returndata.length > 0) { - // Return data is optional - require(abi.decode(returndata, (bool)), "SafeERC20: ERC20 operation did not succeed"); - } - } -} - - - - - - - - - - - - - - -/** - * @dev Provides information about the current execution context, including the - * sender of the transaction and its data. While these are generally available - * via msg.sender and msg.data, they should not be accessed in such a direct - * manner, since when dealing with meta-transactions the account sending and - * paying for execution may not be the actual sender (as far as an application - * is concerned). - * - * This contract is only required for intermediate, library-like contracts. - */ -abstract contract Context { - function _msgSender() internal view virtual returns (address) { - return msg.sender; - } - - function _msgData() internal view virtual returns (bytes calldata) { - return msg.data; - } -} - - -/** - * @dev Contract module which provides a basic access control mechanism, where - * there is an account (an owner) that can be granted exclusive access to - * specific functions. - * - * By default, the owner account will be the one that deploys the contract. This - * can later be changed with {transferOwnership}. - * - * This module is used through inheritance. It will make available the modifier - * `onlyOwner`, which can be applied to your functions to restrict their use to - * the owner. - */ -abstract contract Ownable is Context { - address private _owner; - - event OwnershipTransferred(address indexed previousOwner, address indexed newOwner); - - /** - * @dev Initializes the contract setting the deployer as the initial owner. - */ - constructor() { - _transferOwnership(_msgSender()); - } - - /** - * @dev Throws if called by any account other than the owner. - */ - modifier onlyOwner() { - _checkOwner(); - _; - } - - /** - * @dev Returns the address of the current owner. - */ - function owner() public view virtual returns (address) { - return _owner; - } - - /** - * @dev Throws if the sender is not the owner. - */ - function _checkOwner() internal view virtual { - require(owner() == _msgSender(), "Ownable: caller is not the owner"); - } - - /** - * @dev Leaves the contract without owner. It will not be possible to call - * `onlyOwner` functions anymore. Can only be called by the current owner. - * - * NOTE: Renouncing ownership will leave the contract without an owner, - * thereby removing any functionality that is only available to the owner. - */ - function renounceOwnership() public virtual onlyOwner { - _transferOwnership(address(0)); - } - - /** - * @dev Transfers ownership of the contract to a new account (`newOwner`). - * Can only be called by the current owner. - */ - function transferOwnership(address newOwner) public virtual onlyOwner { - require(newOwner != address(0), "Ownable: new owner is the zero address"); - _transferOwnership(newOwner); - } - - /** - * @dev Transfers ownership of the contract to a new account (`newOwner`). - * Internal function without access restriction. - */ - function _transferOwnership(address newOwner) internal virtual { - address oldOwner = _owner; - _owner = newOwner; - emit OwnershipTransferred(oldOwner, newOwner); - } -} - - -contract Operator is Ownable { - address public operator; - uint256 constant baseRate = 10000; - - modifier onlyOperator { - require(msg.sender == owner() || msg.sender == operator, "no permission"); - _; - } - - function setOperator(address operator_) external onlyOwner { - operator = operator_; - } - - - function getCurrTime() external view returns(uint256) { - return block.timestamp; - } - - function getBlockNum() external view returns(uint256) { - return block.number; - } - -} - - - - - -/** - * @dev Library for managing - * https://en.wikipedia.org/wiki/Set_(abstract_data_type)[sets] of primitive - * types. - * - * Sets have the following properties: - * - * - Elements are added, removed, and checked for existence in constant time - * (O(1)). - * - Elements are enumerated in O(n). No guarantees are made on the ordering. - * - * ``` - * contract Example { - * // Add the library methods - * using EnumerableSet for EnumerableSet.AddressSet; - * - * // Declare a set state variable - * EnumerableSet.AddressSet private mySet; - * } - * ``` - * - * As of v3.3.0, sets of type `bytes32` (`Bytes32Set`), `address` (`AddressSet`) - * and `uint256` (`UintSet`) are supported. - * - * [WARNING] - * ==== - * Trying to delete such a structure from storage will likely result in data corruption, rendering the structure unusable. - * See https://github.com/ethereum/solidity/pull/11843[ethereum/solidity#11843] for more info. - * - * In order to clean an EnumerableSet, you can either remove all elements one by one or create a fresh instance using an array of EnumerableSet. - * ==== - */ - -library EnumerableSet { - // To implement this library for multiple types with as little code - // repetition as possible, we write it in terms of a generic Set type with - // bytes32 values. - // The Set implementation uses private functions, and user-facing - // implementations (such as AddressSet) are just wrappers around the - // underlying Set. - // This means that we can only create new EnumerableSets for types that fit - // in bytes32. - - struct Set { - // Storage of set values - bytes32[] _values; - // Position of the value in the `values` array, plus 1 because index 0 - // means a value is not in the set. - mapping(bytes32 => uint256) _indexes; - } - - /** - * @dev Add a value to a set. O(1). - * - * Returns true if the value was added to the set, that is if it was not - * already present. - */ - function _add(Set storage set, bytes32 value) private returns (bool) { - if (!_contains(set, value)) { - set._values.push(value); - // The value is stored at length-1, but we add 1 to all indexes - // and use 0 as a sentinel value - set._indexes[value] = set._values.length; - return true; - } else { - return false; - } - } - - /** - * @dev Removes a value from a set. O(1). - * - * Returns true if the value was removed from the set, that is if it was - * present. - */ - function _remove(Set storage set, bytes32 value) private returns (bool) { - // We read and store the value's index to prevent multiple reads from the same storage slot - uint256 valueIndex = set._indexes[value]; - - if (valueIndex != 0) { - // Equivalent to contains(set, value) - // To delete an element from the _values array in O(1), we swap the element to delete with the last one in - // the array, and then remove the last element (sometimes called as 'swap and pop'). - // This modifies the order of the array, as noted in {at}. - - uint256 toDeleteIndex = valueIndex - 1; - uint256 lastIndex = set._values.length - 1; - - if (lastIndex != toDeleteIndex) { - bytes32 lastValue = set._values[lastIndex]; - - // Move the last value to the index where the value to delete is - set._values[toDeleteIndex] = lastValue; - // Update the index for the moved value - set._indexes[lastValue] = valueIndex; // Replace lastValue's index to valueIndex - } - - // Delete the slot where the moved value was stored - set._values.pop(); - - // Delete the index for the deleted slot - delete set._indexes[value]; - - return true; - } else { - return false; - } - } - - /** - * @dev Returns true if the value is in the set. O(1). - */ - function _contains(Set storage set, bytes32 value) private view returns (bool) { - return set._indexes[value] != 0; - } - - /** - * @dev Returns the number of values on the set. O(1). - */ - function _length(Set storage set) private view returns (uint256) { - return set._values.length; - } - - /** - * @dev Returns the value stored at position `index` in the set. O(1). - * - * Note that there are no guarantees on the ordering of values inside the - * array, and it may change when more values are added or removed. - * - * Requirements: - * - * - `index` must be strictly less than {length}. - */ - function _at(Set storage set, uint256 index) private view returns (bytes32) { - return set._values[index]; - } - - /** - * @dev Return the entire set in an array - * - * WARNING: This operation will copy the entire storage to memory, which can be quite expensive. This is designed - * to mostly be used by view accessors that are queried without any gas fees. Developers should keep in mind that - * this function has an unbounded cost, and using it as part of a state-changing function may render the function - * uncallable if the set grows to a point where copying to memory consumes too much gas to fit in a block. - */ - function _values(Set storage set) private view returns (bytes32[] memory) { - return set._values; - } - - // Bytes32Set - - struct Bytes32Set { - Set _inner; - } - - /** - * @dev Add a value to a set. O(1). - * - * Returns true if the value was added to the set, that is if it was not - * already present. - */ - function add(Bytes32Set storage set, bytes32 value) internal returns (bool) { - return _add(set._inner, value); - } - - /** - * @dev Removes a value from a set. O(1). - * - * Returns true if the value was removed from the set, that is if it was - * present. - */ - function remove(Bytes32Set storage set, bytes32 value) internal returns (bool) { - return _remove(set._inner, value); - } - - /** - * @dev Returns true if the value is in the set. O(1). - */ - function contains(Bytes32Set storage set, bytes32 value) internal view returns (bool) { - return _contains(set._inner, value); - } - - /** - * @dev Returns the number of values in the set. O(1). - */ - function length(Bytes32Set storage set) internal view returns (uint256) { - return _length(set._inner); - } - - /** - * @dev Returns the value stored at position `index` in the set. O(1). - * - * Note that there are no guarantees on the ordering of values inside the - * array, and it may change when more values are added or removed. - * - * Requirements: - * - * - `index` must be strictly less than {length}. - */ - function at(Bytes32Set storage set, uint256 index) internal view returns (bytes32) { - return _at(set._inner, index); - } - - /** - * @dev Return the entire set in an array - * - * WARNING: This operation will copy the entire storage to memory, which can be quite expensive. This is designed - * to mostly be used by view accessors that are queried without any gas fees. Developers should keep in mind that - * this function has an unbounded cost, and using it as part of a state-changing function may render the function - * uncallable if the set grows to a point where copying to memory consumes too much gas to fit in a block. - */ - function values(Bytes32Set storage set) internal view returns (bytes32[] memory) { - return _values(set._inner); - } - - // AddressSet - - struct AddressSet { - Set _inner; - } - - /** - * @dev Add a value to a set. O(1). - * - * Returns true if the value was added to the set, that is if it was not - * already present. - */ - function add(AddressSet storage set, address value) internal returns (bool) { - return _add(set._inner, bytes32(uint256(uint160(value)))); - } - - /** - * @dev Removes a value from a set. O(1). - * - * Returns true if the value was removed from the set, that is if it was - * present. - */ - function remove(AddressSet storage set, address value) internal returns (bool) { - return _remove(set._inner, bytes32(uint256(uint160(value)))); - } - - /** - * @dev Returns true if the value is in the set. O(1). - */ - function contains(AddressSet storage set, address value) internal view returns (bool) { - return _contains(set._inner, bytes32(uint256(uint160(value)))); - } - - /** - * @dev Returns the number of values in the set. O(1). - */ - function length(AddressSet storage set) internal view returns (uint256) { - return _length(set._inner); - } - - /** - * @dev Returns the value stored at position `index` in the set. O(1). - * - * Note that there are no guarantees on the ordering of values inside the - * array, and it may change when more values are added or removed. - * - * Requirements: - * - * - `index` must be strictly less than {length}. - */ - function at(AddressSet storage set, uint256 index) internal view returns (address) { - return address(uint160(uint256(_at(set._inner, index)))); - } - - /** - * @dev Return the entire set in an array - * - * WARNING: This operation will copy the entire storage to memory, which can be quite expensive. This is designed - * to mostly be used by view accessors that are queried without any gas fees. Developers should keep in mind that - * this function has an unbounded cost, and using it as part of a state-changing function may render the function - * uncallable if the set grows to a point where copying to memory consumes too much gas to fit in a block. - */ - function values(AddressSet storage set) internal view returns (address[] memory) { - bytes32[] memory store = _values(set._inner); - address[] memory result; - - /// @solidity memory-safe-assembly - assembly { - result := store - } - - return result; - } - - // UintSet - - struct UintSet { - Set _inner; - } - - /** - * @dev Add a value to a set. O(1). - * - * Returns true if the value was added to the set, that is if it was not - * already present. - */ - function add(UintSet storage set, uint256 value) internal returns (bool) { - return _add(set._inner, bytes32(value)); - } - - /** - * @dev Removes a value from a set. O(1). - * - * Returns true if the value was removed from the set, that is if it was - * present. - */ - function remove(UintSet storage set, uint256 value) internal returns (bool) { - return _remove(set._inner, bytes32(value)); - } - - /** - * @dev Returns true if the value is in the set. O(1). - */ - function contains(UintSet storage set, uint256 value) internal view returns (bool) { - return _contains(set._inner, bytes32(value)); - } - - /** - * @dev Returns the number of values on the set. O(1). - */ - function length(UintSet storage set) internal view returns (uint256) { - return _length(set._inner); - } - - /** - * @dev Returns the value stored at position `index` in the set. O(1). - * - * Note that there are no guarantees on the ordering of values inside the - * array, and it may change when more values are added or removed. - * - * Requirements: - * - * - `index` must be strictly less than {length}. - */ - function at(UintSet storage set, uint256 index) internal view returns (uint256) { - return uint256(_at(set._inner, index)); - } - - /** - * @dev Return the entire set in an array - * - * WARNING: This operation will copy the entire storage to memory, which can be quite expensive. This is designed - * to mostly be used by view accessors that are queried without any gas fees. Developers should keep in mind that - * this function has an unbounded cost, and using it as part of a state-changing function may render the function - * uncallable if the set grows to a point where copying to memory consumes too much gas to fit in a block. - */ - function values(UintSet storage set) internal view returns (uint256[] memory) { - bytes32[] memory store = _values(set._inner); - uint256[] memory result; - - /// @solidity memory-safe-assembly - assembly { - result := store - } - - return result; - } -} - - -contract ActivityPool is Operator { - using SafeMath for uint256; - using SafeERC20 for IERC20; - using EnumerableSet for EnumerableSet.AddressSet; - using EnumerableSet for EnumerableSet.UintSet; - - event AddNewAct(uint256 id); - event Bet(address user, uint256 pID, uint256 bType, uint256 amount, uint256 time); - event SetPrize(uint256 pID, uint256 bType); - event Claim(address user, uint256 pID, uint256 bType, uint256 amount); - event RemovePeriodAct(uint256 pID); - - uint256 public constant muti = 1e18; - uint256 public periodID; - uint256 public betID; - - struct UserInfo { - address user; - uint256 pID; - uint256 amount; - uint256 betTime; - uint256 bType; - uint256 claimAmount; - } - - struct ActInfo { - string name; - string aName; - string bName; - address rewardToken; - uint256 startTime; - uint256 endTime; - uint256 minAmount; - uint256 maxAmount; - uint256 aAmount; - uint256 bAmount; - uint256 winType; - bool isBet; - } - - struct TimeInfo { - uint256 time; - uint256 aAmount; - uint256 bAmount; - } - - struct BestInfo { - address aUser; - address bUser; - uint256 aBet; - uint256 bBet; - } - - mapping(uint256 => BestInfo) bestInfo; - mapping(uint256 => uint256) public timeID; - mapping(uint256 => mapping(uint256 => TimeInfo)) public timeInfo; - mapping(address => mapping(uint256 => uint256)) public userBet; - mapping(uint256 => UserInfo) public betInfo; - mapping(uint256 => uint256) public perAmount; - mapping(uint256 => ActInfo) public actInfo; - mapping(uint256 => mapping(uint256 => string)) public descripName; - - mapping(address => EnumerableSet.UintSet) userPid; - mapping(uint256 => EnumerableSet.AddressSet) aUsers; - mapping(uint256 => EnumerableSet.AddressSet) bUsers; - EnumerableSet.UintSet activePeriod; - EnumerableSet.UintSet removePeriod; - - function addNewAct( - string memory name, - string memory aName, - string memory bName, - address token, - uint256 startTime, - uint256 endTime, - uint256 minAmount, - uint256 maxAmount - ) external onlyOperator { - - checkAdd(msg.sender, startTime, endTime, minAmount, maxAmount); - uint256 id = ++periodID; - actInfo[id].name = name; - actInfo[id].aName = aName; - actInfo[id].bName = bName; - actInfo[id].startTime = startTime; - actInfo[id].endTime = endTime; - actInfo[id].minAmount = minAmount; - actInfo[id].maxAmount = maxAmount; - actInfo[id].rewardToken = token; - descripName[id][1] = aName; - descripName[id][2] = bName; - activePeriod.add(id); - - emit AddNewAct(id); - } - - - function removePeriodAct(uint256 pID) external onlyOperator { - checkRemove(pID); - - activePeriod.remove(pID); - removePeriod.add(pID); - - emit RemovePeriodAct(pID); - } - - - function bet(uint256 pID, uint256 bType, uint256 amount) external payable { - checkBet(msg.sender, pID, bType, amount); - if(actInfo[pID].rewardToken == address(0)) { - require(msg.value == amount, "value err"); - } else { - require(msg.value == 0, "value amount err"); - } - - if(bType == 1) { - if(amount > bestInfo[pID].aBet) { - bestInfo[pID].aUser = msg.sender; - bestInfo[pID].aBet = amount; - } - } else { - if(amount > bestInfo[pID].bBet) { - bestInfo[pID].bUser = msg.sender; - bestInfo[pID].bBet = amount; - } - } - - userPid[msg.sender].add(pID); - uint256 id = ++betID; - userBet[msg.sender][pID] = id; - - if(bType == 1) { - aUsers[pID].add(msg.sender); - actInfo[pID].aAmount = actInfo[pID].aAmount.add(amount); - } else { - bUsers[pID].add(msg.sender); - actInfo[pID].bAmount = actInfo[pID].bAmount.add(amount); - } - - actInfo[pID].isBet = true; - betInfo[id].user = msg.sender; - betInfo[id].pID = pID; - betInfo[id].amount = amount; - betInfo[id].betTime = block.timestamp; - betInfo[id].bType = bType; - - uint256 tID = ++timeID[pID]; - timeInfo[pID][tID].time = block.timestamp; - timeInfo[pID][tID].aAmount = actInfo[pID].aAmount; - timeInfo[pID][tID].bAmount = actInfo[pID].bAmount; - - if(actInfo[pID].rewardToken != address(0)) { - IERC20(actInfo[pID].rewardToken).safeTransferFrom(msg.sender, address(this), amount); - } - emit Bet(msg.sender, pID, bType, amount, betInfo[id].betTime); - } - - function setPrize(uint256 pID, uint256 bType) external onlyOperator { - checkSetPrize(msg.sender, pID, bType); - - if(block.timestamp <= actInfo[pID].startTime) { - actInfo[pID].startTime = block.timestamp; - - } - actInfo[pID].endTime = block.timestamp; - - actInfo[pID].winType = bType; - perAmount[pID] = getPerAmount(pID, bType); - - emit SetPrize(pID, bType); - } - - function recive() public payable {} - - function claim(uint256 pID) external { - uint256 amount = checkClaim(msg.sender, pID); - - uint256 id = userBet[msg.sender][pID]; - betInfo[id].claimAmount = amount; - if(actInfo[pID].rewardToken != address(0)) { - IERC20(actInfo[pID].rewardToken).safeTransfer(msg.sender, amount); - } else { - payable(msg.sender).transfer(amount); - } - - emit Claim(msg.sender, pID, betInfo[id].bType, amount); - } - - function checkClaim(address user, uint256 pID) public view returns(uint256 amount) { - require(userPid[user].contains(pID), "not bet"); - uint256 id = userBet[user][pID]; - require(betInfo[id].user == user, "not user"); - require(actInfo[pID].winType != 0, "not prize"); - require(betInfo[id].claimAmount == 0, "has claim"); - - if(actInfo[pID].winType != 3) { - require(actInfo[pID].winType == betInfo[id].bType, "not right"); - amount = perAmount[pID].mul(betInfo[id].amount).div(muti); - require(amount > 0, "no amount"); - } else { - amount = betInfo[id].amount; - } - - return amount; - } - - function getActualRate( - address user, - uint256 pID, - uint256 bType, - uint256 amount - ) external view returns(uint256, uint256, bool) { - if(bType < 1 || bType > 2 || !activePeriod.contains(pID)) { - return (0, 0, false); - } else if(userBet[user][pID] != 0 || actInfo[pID].winType != 0 || amount == 0) { - (uint256 ra, uint256 rb) = getRate(pID, timeID[pID]); - return (ra, rb, false); - } else { - (uint256 aAmount, uint256 bAmount) = (actInfo[pID].aAmount, actInfo[pID].bAmount); - if(bType == 1) { - aAmount = aAmount.add(amount); - } else { - bAmount = bAmount.add(amount); - } - - uint256 total = aAmount.add(bAmount); - if(bAmount == 0 && aAmount != 0) { - return (muti, 0, true); - } - if(bAmount != 0 && aAmount == 0) { - return (0, muti, true); - } - return (total.mul(muti).div(aAmount), total.mul(muti).div(bAmount), true); - } - } - - function getRate(uint256 pID, uint256 tID) public view returns(uint256, uint256) { - (uint256 aAmount, uint256 bAmount) = (timeInfo[pID][tID].aAmount, timeInfo[pID][tID].bAmount); - uint256 total = aAmount.add(bAmount); - if(total == 0) { - return (0, 0); - } - if(bAmount == 0 && aAmount != 0) { - return (muti, 0); - } - if(bAmount != 0 && aAmount == 0) { - return (0, muti); - } - return (total.mul(muti).div(aAmount), total.mul(muti).div(bAmount)); - } - - function getBestInfo(uint256 pID) - external - view - returns(address aUser, address bUser, uint256 aBet, uint256 bBet, uint256 aReward, uint256 bReward) - { - aUser = bestInfo[pID].aUser; - bUser = bestInfo[pID].bUser; - aBet = bestInfo[pID].aBet; - bBet = bestInfo[pID].bBet; - aReward = getPerAmount(pID, 1).mul(aBet).div(muti); - bReward = getPerAmount(pID, 2).mul(bBet).div(muti); - } - - function getPerAmount(uint256 pID, uint256 bType) public view returns(uint256) { - uint256 total = actInfo[pID].aAmount.add(actInfo[pID].bAmount); - if(total == 0) { - return 0; - } - - if(actInfo[pID].winType == 3) { - return muti; - } - - if(bType == 1) { - if(actInfo[pID].aAmount == 0 || actInfo[pID].winType == 2) { - return 0; - } - return total.mul(muti).div(actInfo[pID].aAmount); - } - - if(bType == 2) { - if(actInfo[pID].bAmount == 0 || actInfo[pID].winType == 1) { - return 0; - } - return total.mul(muti).div(actInfo[pID].bAmount); - } - - return 0; - - } - - function checkSetPrize(address user, uint256 pID, uint256 bType) public view returns(bool) { - require(user == owner() || user == operator, "no permission"); - require(bType > 0 && bType <= 3, "type err"); - require(activePeriod.contains(pID), "not active"); - require(actInfo[pID].winType == 0, "has set"); - - return true; - } - - function checkBet( - address user, - uint256 pID, - uint256 bType, - uint256 amount - ) public view returns(bool) { - require(activePeriod.contains(pID), "not active"); - require(actInfo[pID].startTime <= block.timestamp, "not start"); - require(actInfo[pID].endTime > block.timestamp, "has end"); - require(!userPid[user].contains(pID), "has bet"); - require(bType > 0 && bType < 3, "type err"); - require(amount >= actInfo[pID].minAmount && amount <= actInfo[pID].maxAmount, "amount err"); - if(actInfo[pID].rewardToken != address(0)) { - require(IERC20(actInfo[pID].rewardToken).allowance(user, address(this)) >= amount, "not approve enough"); - require(IERC20(actInfo[pID].rewardToken).balanceOf(user) >= amount, "not enough"); - } else { - require(user.balance >= amount, "main token err"); - } - - return true; - } - - - function checkRemove(uint256 pID) public view returns(bool) { - require(activePeriod.contains(pID), "not in"); - require(!actInfo[pID].isBet, "has bet"); - - return true; - } - - function checkAdd( - address user, - uint256 startTime, - uint256 endTime, - uint256 minAmount, - uint256 maxAmount - ) public view returns(bool) { - require(user == owner() || user == operator, "no permission"); - require(startTime > block.timestamp, "startTime err"); - require(endTime > startTime, "endTime err"); - require(minAmount > 0 && maxAmount > minAmount, "amount err"); - - return true; - } - - function getStatus(uint256 pID) external view returns(uint256) { - if(!removePeriod.contains(pID) && !activePeriod.contains(pID)) { - return 5; - } else if(removePeriod.contains(pID)) { - return 6; - } else if(block.timestamp < actInfo[pID].startTime) { - return 1; - } else if ( - actInfo[pID].startTime <= block.timestamp && - actInfo[pID].endTime > block.timestamp - ) { - return 2; - } else if (actInfo[pID].endTime <= block.timestamp && actInfo[pID].winType == 0){ - return 3; - } else if(actInfo[pID].winType != 0) { - return 4; - } - return 0; - } - - function getUserPidNum(address user) external view returns(uint256) { - return userPid[user].length(); - } - - function getUserPid(address user, uint256 index) external view returns(uint256) { - return userPid[user].at(index); - } - - function getAUsersNum(uint256 pID) external view returns(uint256) { - return aUsers[pID].length(); - } - - function getAUsers(uint256 pID, uint256 index) external view returns(address) { - return aUsers[pID].at(index); - } - - function getBUsersNum(uint256 pID) external view returns(uint256) { - return bUsers[pID].length(); - } - - function getBUsers(uint256 pID, uint256 index) external view returns(address) { - return bUsers[pID].at(index); - } - - function getActivePeriodNum() external view returns(uint256) { - return activePeriod.length(); - } - - function getActivePeriod(uint256 index) external view returns(uint256) { - return activePeriod.at(index); - } - - function getRemovePeriodNum() external view returns(uint256) { - return removePeriod.length(); - } - - function getRemovePeriod(uint256 index) external view returns(uint256) { - return removePeriod.at(index); - } -} \ No newline at end of file diff --git a/app/api/uploads/ActivityPool-1729808113420-601666536.sol b/app/api/uploads/ActivityPool-1729808113420-601666536.sol deleted file mode 100644 index daf3372..0000000 --- a/app/api/uploads/ActivityPool-1729808113420-601666536.sol +++ /dev/null @@ -1,1648 +0,0 @@ -// SPDX-License-Identifier: MIT -// OpenZeppelin Contracts (last updated v4.7.0) (utils/Address.sol) - -pragma solidity ^0.8.1; - -/** - * @dev Collection of functions related to the address type - */ -library Address { - /** - * @dev Returns true if `account` is a contract. - * - * [IMPORTANT] - * ==== - * It is unsafe to assume that an address for which this function returns - * false is an externally-owned account (EOA) and not a contract. - * - * Among others, `isContract` will return false for the following - * types of addresses: - * - * - an externally-owned account - * - a contract in construction - * - an address where a contract will be created - * - an address where a contract lived, but was destroyed - * ==== - * - * [IMPORTANT] - * ==== - * You shouldn't rely on `isContract` to protect against flash loan attacks! - * - * Preventing calls from contracts is highly discouraged. It breaks composability, breaks support for smart wallets - * like Gnosis Safe, and does not provide security since it can be circumvented by calling from a contract - * constructor. - * ==== - */ - function isContract(address account) internal view returns (bool) { - // This method relies on extcodesize/address.code.length, which returns 0 - // for contracts in construction, since the code is only stored at the end - // of the constructor execution. - - return account.code.length > 0; - } - - /** - * @dev Replacement for Solidity's `transfer`: sends `amount` wei to - * `recipient`, forwarding all available gas and reverting on errors. - * - * https://eips.ethereum.org/EIPS/eip-1884[EIP1884] increases the gas cost - * of certain opcodes, possibly making contracts go over the 2300 gas limit - * imposed by `transfer`, making them unable to receive funds via - * `transfer`. {sendValue} removes this limitation. - * - * https://diligence.consensys.net/posts/2019/09/stop-using-soliditys-transfer-now/[Learn more]. - * - * IMPORTANT: because control is transferred to `recipient`, care must be - * taken to not create reentrancy vulnerabilities. Consider using - * {ReentrancyGuard} or the - * https://solidity.readthedocs.io/en/v0.5.11/security-considerations.html#use-the-checks-effects-interactions-pattern[checks-effects-interactions pattern]. - */ - function sendValue(address payable recipient, uint256 amount) internal { - require(address(this).balance >= amount, "Address: insufficient balance"); - - (bool success, ) = recipient.call{value: amount}(""); - require(success, "Address: unable to send value, recipient may have reverted"); - } - - /** - * @dev Performs a Solidity function call using a low level `call`. A - * plain `call` is an unsafe replacement for a function call: use this - * function instead. - * - * If `target` reverts with a revert reason, it is bubbled up by this - * function (like regular Solidity function calls). - * - * Returns the raw returned data. To convert to the expected return value, - * use https://solidity.readthedocs.io/en/latest/units-and-global-variables.html?highlight=abi.decode#abi-encoding-and-decoding-functions[`abi.decode`]. - * - * Requirements: - * - * - `target` must be a contract. - * - calling `target` with `data` must not revert. - * - * _Available since v3.1._ - */ - function functionCall(address target, bytes memory data) internal returns (bytes memory) { - return functionCallWithValue(target, data, 0, "Address: low-level call failed"); - } - - /** - * @dev Same as {xref-Address-functionCall-address-bytes-}[`functionCall`], but with - * `errorMessage` as a fallback revert reason when `target` reverts. - * - * _Available since v3.1._ - */ - function functionCall( - address target, - bytes memory data, - string memory errorMessage - ) internal returns (bytes memory) { - return functionCallWithValue(target, data, 0, errorMessage); - } - - /** - * @dev Same as {xref-Address-functionCall-address-bytes-}[`functionCall`], - * but also transferring `value` wei to `target`. - * - * Requirements: - * - * - the calling contract must have an ETH balance of at least `value`. - * - the called Solidity function must be `payable`. - * - * _Available since v3.1._ - */ - function functionCallWithValue( - address target, - bytes memory data, - uint256 value - ) internal returns (bytes memory) { - return functionCallWithValue(target, data, value, "Address: low-level call with value failed"); - } - - /** - * @dev Same as {xref-Address-functionCallWithValue-address-bytes-uint256-}[`functionCallWithValue`], but - * with `errorMessage` as a fallback revert reason when `target` reverts. - * - * _Available since v3.1._ - */ - function functionCallWithValue( - address target, - bytes memory data, - uint256 value, - string memory errorMessage - ) internal returns (bytes memory) { - require(address(this).balance >= value, "Address: insufficient balance for call"); - (bool success, bytes memory returndata) = target.call{value: value}(data); - return verifyCallResultFromTarget(target, success, returndata, errorMessage); - } - - /** - * @dev Same as {xref-Address-functionCall-address-bytes-}[`functionCall`], - * but performing a static call. - * - * _Available since v3.3._ - */ - function functionStaticCall(address target, bytes memory data) internal view returns (bytes memory) { - return functionStaticCall(target, data, "Address: low-level static call failed"); - } - - /** - * @dev Same as {xref-Address-functionCall-address-bytes-string-}[`functionCall`], - * but performing a static call. - * - * _Available since v3.3._ - */ - function functionStaticCall( - address target, - bytes memory data, - string memory errorMessage - ) internal view returns (bytes memory) { - (bool success, bytes memory returndata) = target.staticcall(data); - return verifyCallResultFromTarget(target, success, returndata, errorMessage); - } - - /** - * @dev Same as {xref-Address-functionCall-address-bytes-}[`functionCall`], - * but performing a delegate call. - * - * _Available since v3.4._ - */ - function functionDelegateCall(address target, bytes memory data) internal returns (bytes memory) { - return functionDelegateCall(target, data, "Address: low-level delegate call failed"); - } - - /** - * @dev Same as {xref-Address-functionCall-address-bytes-string-}[`functionCall`], - * but performing a delegate call. - * - * _Available since v3.4._ - */ - function functionDelegateCall( - address target, - bytes memory data, - string memory errorMessage - ) internal returns (bytes memory) { - (bool success, bytes memory returndata) = target.delegatecall(data); - return verifyCallResultFromTarget(target, success, returndata, errorMessage); - } - - /** - * @dev Tool to verify that a low level call to smart-contract was successful, and revert (either by bubbling - * the revert reason or using the provided one) in case of unsuccessful call or if target was not a contract. - * - * _Available since v4.8._ - */ - function verifyCallResultFromTarget( - address target, - bool success, - bytes memory returndata, - string memory errorMessage - ) internal view returns (bytes memory) { - if (success) { - if (returndata.length == 0) { - // only check isContract if the call was successful and the return data is empty - // otherwise we already know that it was a contract - require(isContract(target), "Address: call to non-contract"); - } - return returndata; - } else { - _revert(returndata, errorMessage); - } - } - - /** - * @dev Tool to verify that a low level call was successful, and revert if it wasn't, either by bubbling the - * revert reason or using the provided one. - * - * _Available since v4.3._ - */ - function verifyCallResult( - bool success, - bytes memory returndata, - string memory errorMessage - ) internal pure returns (bytes memory) { - if (success) { - return returndata; - } else { - _revert(returndata, errorMessage); - } - } - - function _revert(bytes memory returndata, string memory errorMessage) private pure { - // Look for revert reason and bubble it up if present - if (returndata.length > 0) { - // The easiest way to bubble the revert reason is using memory via assembly - /// @solidity memory-safe-assembly - assembly { - let returndata_size := mload(returndata) - revert(add(32, returndata), returndata_size) - } - } else { - revert(errorMessage); - } - } -} - -// OpenZeppelin Contracts (last updated v4.6.0) (token/ERC20/IERC20.sol) - - - -/** - * @dev Interface of the ERC20 standard as defined in the EIP. - */ -interface IERC20 { - /** - * @dev Emitted when `value` tokens are moved from one account (`from`) to - * another (`to`). - * - * Note that `value` may be zero. - */ - event Transfer(address indexed from, address indexed to, uint256 value); - - /** - * @dev Emitted when the allowance of a `spender` for an `owner` is set by - * a call to {approve}. `value` is the new allowance. - */ - event Approval(address indexed owner, address indexed spender, uint256 value); - - /** - * @dev Returns the amount of tokens in existence. - */ - function totalSupply() external view returns (uint256); - - /** - * @dev Returns the amount of tokens owned by `account`. - */ - function balanceOf(address account) external view returns (uint256); - - /** - * @dev Moves `amount` tokens from the caller's account to `to`. - * - * Returns a boolean value indicating whether the operation succeeded. - * - * Emits a {Transfer} event. - */ - function transfer(address to, uint256 amount) external returns (bool); - - /** - * @dev Returns the remaining number of tokens that `spender` will be - * allowed to spend on behalf of `owner` through {transferFrom}. This is - * zero by default. - * - * This value changes when {approve} or {transferFrom} are called. - */ - function allowance(address owner, address spender) external view returns (uint256); - - /** - * @dev Sets `amount` as the allowance of `spender` over the caller's tokens. - * - * Returns a boolean value indicating whether the operation succeeded. - * - * IMPORTANT: Beware that changing an allowance with this method brings the risk - * that someone may use both the old and the new allowance by unfortunate - * transaction ordering. One possible solution to mitigate this race - * condition is to first reduce the spender's allowance to 0 and set the - * desired value afterwards: - * https://github.com/ethereum/EIPs/issues/20#issuecomment-263524729 - * - * Emits an {Approval} event. - */ - function approve(address spender, uint256 amount) external returns (bool); - - /** - * @dev Moves `amount` tokens from `from` to `to` using the - * allowance mechanism. `amount` is then deducted from the caller's - * allowance. - * - * Returns a boolean value indicating whether the operation succeeded. - * - * Emits a {Transfer} event. - */ - function transferFrom( - address from, - address to, - uint256 amount - ) external returns (bool); - - - function mint(address account_, uint256 amount_) external; - - function burn(uint256 amount) external; - -} - - - - - - - - - - - -/** - * @dev Wrappers over Solidity's arithmetic operations with added overflow - * checks. - * - * Arithmetic operations in Solidity wrap on overflow. This can easily result - * in bugs, because programmers usually assume that an overflow raises an - * error, which is the standard behavior in high level programming languages. - * `SafeMath` restores this intuition by reverting the transaction when an - * operation overflows. - * - * Using this library instead of the unchecked operations eliminates an entire - * class of bugs, so it's recommended to use it always. - */ -library SafeMath { - /** - * @dev Returns the addition of two unsigned integers, reverting on - * overflow. - * - * Counterpart to Solidity's `+` operator. - * - * Requirements: - * - * - Addition cannot overflow. - */ - function add(uint256 a, uint256 b) internal pure returns (uint256) { - uint256 c = a + b; - require(c >= a, "SafeMath: addition overflow"); - - return c; - } - - /** - * @dev Returns the subtraction of two unsigned integers, reverting on - * overflow (when the result is negative). - * - * Counterpart to Solidity's `-` operator. - * - * Requirements: - * - * - Subtraction cannot overflow. - */ - function sub(uint256 a, uint256 b) internal pure returns (uint256) { - return sub(a, b, "SafeMath: subtraction overflow"); - } - - /** - * @dev Returns the subtraction of two unsigned integers, reverting with custom message on - * overflow (when the result is negative). - * - * Counterpart to Solidity's `-` operator. - * - * Requirements: - * - * - Subtraction cannot overflow. - */ - function sub( - uint256 a, - uint256 b, - string memory errorMessage - ) internal pure returns (uint256) { - require(b <= a, errorMessage); - uint256 c = a - b; - - return c; - } - - /** - * @dev Returns the multiplication of two unsigned integers, reverting on - * overflow. - * - * Counterpart to Solidity's `*` operator. - * - * Requirements: - * - * - Multiplication cannot overflow. - */ - function mul(uint256 a, uint256 b) internal pure returns (uint256) { - // Gas optimization: this is cheaper than requiring 'a' not being zero, but the - // benefit is lost if 'b' is also tested. - // See: https://github.com/OpenZeppelin/openzeppelin-contracts/pull/522 - if (a == 0) { - return 0; - } - - uint256 c = a * b; - require(c / a == b, "SafeMath: multiplication overflow"); - - return c; - } - - /** - * @dev Returns the integer division of two unsigned integers. Reverts on - * division by zero. The result is rounded towards zero. - * - * Counterpart to Solidity's `/` operator. Note: this function uses a - * `revert` opcode (which leaves remaining gas untouched) while Solidity - * uses an invalid opcode to revert (consuming all remaining gas). - * - * Requirements: - * - * - The divisor cannot be zero. - */ - function div(uint256 a, uint256 b) internal pure returns (uint256) { - return div(a, b, "SafeMath: division by zero"); - } - - /** - * @dev Returns the integer division of two unsigned integers. Reverts with custom message on - * division by zero. The result is rounded towards zero. - * - * Counterpart to Solidity's `/` operator. Note: this function uses a - * `revert` opcode (which leaves remaining gas untouched) while Solidity - * uses an invalid opcode to revert (consuming all remaining gas). - * - * Requirements: - * - * - The divisor cannot be zero. - */ - function div( - uint256 a, - uint256 b, - string memory errorMessage - ) internal pure returns (uint256) { - require(b > 0, errorMessage); - uint256 c = a / b; - // assert(a == b * c + a % b); // There is no case in which this doesn't hold - - return c; - } - - /** - * @dev Returns the remainder of dividing two unsigned integers. (unsigned integer modulo), - * Reverts when dividing by zero. - * - * Counterpart to Solidity's `%` operator. This function uses a `revert` - * opcode (which leaves remaining gas untouched) while Solidity uses an - * invalid opcode to revert (consuming all remaining gas). - * - * Requirements: - * - * - The divisor cannot be zero. - */ - function mod(uint256 a, uint256 b) internal pure returns (uint256) { - return mod(a, b, "SafeMath: modulo by zero"); - } - - /** - * @dev Returns the remainder of dividing two unsigned integers. (unsigned integer modulo), - * Reverts with custom message when dividing by zero. - * - * Counterpart to Solidity's `%` operator. This function uses a `revert` - * opcode (which leaves remaining gas untouched) while Solidity uses an - * invalid opcode to revert (consuming all remaining gas). - * - * Requirements: - * - * - The divisor cannot be zero. - */ - function mod( - uint256 a, - uint256 b, - string memory errorMessage - ) internal pure returns (uint256) { - require(b != 0, errorMessage); - return a % b; - } - - // babylonian method (https://en.wikipedia.org/wiki/Methods_of_computing_square_roots#Babylonian_method) - function sqrrt(uint256 a) internal pure returns (uint256 c) { - if (a > 3) { - c = a; - uint256 b = add(div(a, 2), 1); - while (b < c) { - c = b; - b = div(add(div(a, b), b), 2); - } - } else if (a != 0) { - c = 1; - } - } - - /* - * Expects percentage to be trailed by 00, - */ - function percentageAmount(uint256 total_, uint8 percentage_) internal pure returns (uint256 percentAmount_) { - return div(mul(total_, percentage_), 1000); - } - - /* - * Expects percentage to be trailed by 00, - */ - function substractPercentage(uint256 total_, uint8 percentageToSub_) internal pure returns (uint256 result_) { - return sub(total_, div(mul(total_, percentageToSub_), 1000)); - } - - function percentageOfTotal(uint256 part_, uint256 total_) internal pure returns (uint256 percent_) { - return div(mul(part_, 100), total_); - } - - /** - * Taken from Hypersonic https://github.com/M2629/HyperSonic/blob/main/Math.sol - * @dev Returns the average of two numbers. The result is rounded towards - * zero. - */ - function average(uint256 a, uint256 b) internal pure returns (uint256) { - // (a + b) / 2 can overflow, so we distribute - return (a / 2) + (b / 2) + (((a % 2) + (b % 2)) / 2); - } - - function quadraticPricing(uint256 payment_, uint256 multiplier_) internal pure returns (uint256) { - return sqrrt(mul(multiplier_, payment_)); - } - - function bondingCurve(uint256 supply_, uint256 multiplier_) internal pure returns (uint256) { - return mul(multiplier_, supply_); - } -} - -// OpenZeppelin Contracts (last updated v4.7.0) (token/ERC20/utils/SafeERC20.sol) - - - - - -// OpenZeppelin Contracts v4.4.1 (token/ERC20/extensions/draft-IERC20Permit.sol) - - - -/** - * @dev Interface of the ERC20 Permit extension allowing approvals to be made via signatures, as defined in - * https://eips.ethereum.org/EIPS/eip-2612[EIP-2612]. - * - * Adds the {permit} method, which can be used to change an account's ERC20 allowance (see {IERC20-allowance}) by - * presenting a message signed by the account. By not relying on {IERC20-approve}, the token holder account doesn't - * need to send a transaction, and thus is not required to hold Ether at all. - */ -interface IERC20Permit { - /** - * @dev Sets `value` as the allowance of `spender` over ``owner``'s tokens, - * given ``owner``'s signed approval. - * - * IMPORTANT: The same issues {IERC20-approve} has related to transaction - * ordering also apply here. - * - * Emits an {Approval} event. - * - * Requirements: - * - * - `spender` cannot be the zero address. - * - `deadline` must be a timestamp in the future. - * - `v`, `r` and `s` must be a valid `secp256k1` signature from `owner` - * over the EIP712-formatted function arguments. - * - the signature must use ``owner``'s current nonce (see {nonces}). - * - * For more information on the signature format, see the - * https://eips.ethereum.org/EIPS/eip-2612#specification[relevant EIP - * section]. - */ - function permit( - address owner, - address spender, - uint256 value, - uint256 deadline, - uint8 v, - bytes32 r, - bytes32 s - ) external; - - /** - * @dev Returns the current nonce for `owner`. This value must be - * included whenever a signature is generated for {permit}. - * - * Every successful call to {permit} increases ``owner``'s nonce by one. This - * prevents a signature from being used multiple times. - */ - function nonces(address owner) external view returns (uint256); - - /** - * @dev Returns the domain separator used in the encoding of the signature for {permit}, as defined by {EIP712}. - */ - // solhint-disable-next-line func-name-mixedcase - function DOMAIN_SEPARATOR() external view returns (bytes32); -} - - - -/** - * @title SafeERC20 - * @dev Wrappers around ERC20 operations that throw on failure (when the token - * contract returns false). Tokens that return no value (and instead revert or - * throw on failure) are also supported, non-reverting calls are assumed to be - * successful. - * To use this library you can add a `using SafeERC20 for IERC20;` statement to your contract, - * which allows you to call the safe operations as `token.safeTransfer(...)`, etc. - */ -library SafeERC20 { - using Address for address; - - function safeTransfer( - IERC20 token, - address to, - uint256 value - ) internal { - _callOptionalReturn(token, abi.encodeWithSelector(token.transfer.selector, to, value)); - } - - function safeTransferFrom( - IERC20 token, - address from, - address to, - uint256 value - ) internal { - _callOptionalReturn(token, abi.encodeWithSelector(token.transferFrom.selector, from, to, value)); - } - - /** - * @dev Deprecated. This function has issues similar to the ones found in - * {IERC20-approve}, and its usage is discouraged. - * - * Whenever possible, use {safeIncreaseAllowance} and - * {safeDecreaseAllowance} instead. - */ - function safeApprove( - IERC20 token, - address spender, - uint256 value - ) internal { - // safeApprove should only be called when setting an initial allowance, - // or when resetting it to zero. To increase and decrease it, use - // 'safeIncreaseAllowance' and 'safeDecreaseAllowance' - require( - (value == 0) || (token.allowance(address(this), spender) == 0), - "SafeERC20: approve from non-zero to non-zero allowance" - ); - _callOptionalReturn(token, abi.encodeWithSelector(token.approve.selector, spender, value)); - } - - function safeIncreaseAllowance( - IERC20 token, - address spender, - uint256 value - ) internal { - uint256 newAllowance = token.allowance(address(this), spender) + value; - _callOptionalReturn(token, abi.encodeWithSelector(token.approve.selector, spender, newAllowance)); - } - - function safeDecreaseAllowance( - IERC20 token, - address spender, - uint256 value - ) internal { - unchecked { - uint256 oldAllowance = token.allowance(address(this), spender); - require(oldAllowance >= value, "SafeERC20: decreased allowance below zero"); - uint256 newAllowance = oldAllowance - value; - _callOptionalReturn(token, abi.encodeWithSelector(token.approve.selector, spender, newAllowance)); - } - } - - function safePermit( - IERC20Permit token, - address owner, - address spender, - uint256 value, - uint256 deadline, - uint8 v, - bytes32 r, - bytes32 s - ) internal { - uint256 nonceBefore = token.nonces(owner); - token.permit(owner, spender, value, deadline, v, r, s); - uint256 nonceAfter = token.nonces(owner); - require(nonceAfter == nonceBefore + 1, "SafeERC20: permit did not succeed"); - } - - /** - * @dev Imitates a Solidity high-level call (i.e. a regular function call to a contract), relaxing the requirement - * on the return value: the return value is optional (but if data is returned, it must not be false). - * @param token The token targeted by the call. - * @param data The call data (encoded using abi.encode or one of its variants). - */ - function _callOptionalReturn(IERC20 token, bytes memory data) private { - // We need to perform a low level call here, to bypass Solidity's return data size checking mechanism, since - // we're implementing it ourselves. We use {Address.functionCall} to perform this call, which verifies that - // the target address contains contract code and also asserts for success in the low-level call. - - bytes memory returndata = address(token).functionCall(data, "SafeERC20: low-level call failed"); - if (returndata.length > 0) { - // Return data is optional - require(abi.decode(returndata, (bool)), "SafeERC20: ERC20 operation did not succeed"); - } - } -} - - - - - - - - - - - - - - -/** - * @dev Provides information about the current execution context, including the - * sender of the transaction and its data. While these are generally available - * via msg.sender and msg.data, they should not be accessed in such a direct - * manner, since when dealing with meta-transactions the account sending and - * paying for execution may not be the actual sender (as far as an application - * is concerned). - * - * This contract is only required for intermediate, library-like contracts. - */ -abstract contract Context { - function _msgSender() internal view virtual returns (address) { - return msg.sender; - } - - function _msgData() internal view virtual returns (bytes calldata) { - return msg.data; - } -} - - -/** - * @dev Contract module which provides a basic access control mechanism, where - * there is an account (an owner) that can be granted exclusive access to - * specific functions. - * - * By default, the owner account will be the one that deploys the contract. This - * can later be changed with {transferOwnership}. - * - * This module is used through inheritance. It will make available the modifier - * `onlyOwner`, which can be applied to your functions to restrict their use to - * the owner. - */ -abstract contract Ownable is Context { - address private _owner; - - event OwnershipTransferred(address indexed previousOwner, address indexed newOwner); - - /** - * @dev Initializes the contract setting the deployer as the initial owner. - */ - constructor() { - _transferOwnership(_msgSender()); - } - - /** - * @dev Throws if called by any account other than the owner. - */ - modifier onlyOwner() { - _checkOwner(); - _; - } - - /** - * @dev Returns the address of the current owner. - */ - function owner() public view virtual returns (address) { - return _owner; - } - - /** - * @dev Throws if the sender is not the owner. - */ - function _checkOwner() internal view virtual { - require(owner() == _msgSender(), "Ownable: caller is not the owner"); - } - - /** - * @dev Leaves the contract without owner. It will not be possible to call - * `onlyOwner` functions anymore. Can only be called by the current owner. - * - * NOTE: Renouncing ownership will leave the contract without an owner, - * thereby removing any functionality that is only available to the owner. - */ - function renounceOwnership() public virtual onlyOwner { - _transferOwnership(address(0)); - } - - /** - * @dev Transfers ownership of the contract to a new account (`newOwner`). - * Can only be called by the current owner. - */ - function transferOwnership(address newOwner) public virtual onlyOwner { - require(newOwner != address(0), "Ownable: new owner is the zero address"); - _transferOwnership(newOwner); - } - - /** - * @dev Transfers ownership of the contract to a new account (`newOwner`). - * Internal function without access restriction. - */ - function _transferOwnership(address newOwner) internal virtual { - address oldOwner = _owner; - _owner = newOwner; - emit OwnershipTransferred(oldOwner, newOwner); - } -} - - -contract Operator is Ownable { - address public operator; - uint256 constant baseRate = 10000; - - modifier onlyOperator { - require(msg.sender == owner() || msg.sender == operator, "no permission"); - _; - } - - function setOperator(address operator_) external onlyOwner { - operator = operator_; - } - - - function getCurrTime() external view returns(uint256) { - return block.timestamp; - } - - function getBlockNum() external view returns(uint256) { - return block.number; - } - -} - - - - - -/** - * @dev Library for managing - * https://en.wikipedia.org/wiki/Set_(abstract_data_type)[sets] of primitive - * types. - * - * Sets have the following properties: - * - * - Elements are added, removed, and checked for existence in constant time - * (O(1)). - * - Elements are enumerated in O(n). No guarantees are made on the ordering. - * - * ``` - * contract Example { - * // Add the library methods - * using EnumerableSet for EnumerableSet.AddressSet; - * - * // Declare a set state variable - * EnumerableSet.AddressSet private mySet; - * } - * ``` - * - * As of v3.3.0, sets of type `bytes32` (`Bytes32Set`), `address` (`AddressSet`) - * and `uint256` (`UintSet`) are supported. - * - * [WARNING] - * ==== - * Trying to delete such a structure from storage will likely result in data corruption, rendering the structure unusable. - * See https://github.com/ethereum/solidity/pull/11843[ethereum/solidity#11843] for more info. - * - * In order to clean an EnumerableSet, you can either remove all elements one by one or create a fresh instance using an array of EnumerableSet. - * ==== - */ - -library EnumerableSet { - // To implement this library for multiple types with as little code - // repetition as possible, we write it in terms of a generic Set type with - // bytes32 values. - // The Set implementation uses private functions, and user-facing - // implementations (such as AddressSet) are just wrappers around the - // underlying Set. - // This means that we can only create new EnumerableSets for types that fit - // in bytes32. - - struct Set { - // Storage of set values - bytes32[] _values; - // Position of the value in the `values` array, plus 1 because index 0 - // means a value is not in the set. - mapping(bytes32 => uint256) _indexes; - } - - /** - * @dev Add a value to a set. O(1). - * - * Returns true if the value was added to the set, that is if it was not - * already present. - */ - function _add(Set storage set, bytes32 value) private returns (bool) { - if (!_contains(set, value)) { - set._values.push(value); - // The value is stored at length-1, but we add 1 to all indexes - // and use 0 as a sentinel value - set._indexes[value] = set._values.length; - return true; - } else { - return false; - } - } - - /** - * @dev Removes a value from a set. O(1). - * - * Returns true if the value was removed from the set, that is if it was - * present. - */ - function _remove(Set storage set, bytes32 value) private returns (bool) { - // We read and store the value's index to prevent multiple reads from the same storage slot - uint256 valueIndex = set._indexes[value]; - - if (valueIndex != 0) { - // Equivalent to contains(set, value) - // To delete an element from the _values array in O(1), we swap the element to delete with the last one in - // the array, and then remove the last element (sometimes called as 'swap and pop'). - // This modifies the order of the array, as noted in {at}. - - uint256 toDeleteIndex = valueIndex - 1; - uint256 lastIndex = set._values.length - 1; - - if (lastIndex != toDeleteIndex) { - bytes32 lastValue = set._values[lastIndex]; - - // Move the last value to the index where the value to delete is - set._values[toDeleteIndex] = lastValue; - // Update the index for the moved value - set._indexes[lastValue] = valueIndex; // Replace lastValue's index to valueIndex - } - - // Delete the slot where the moved value was stored - set._values.pop(); - - // Delete the index for the deleted slot - delete set._indexes[value]; - - return true; - } else { - return false; - } - } - - /** - * @dev Returns true if the value is in the set. O(1). - */ - function _contains(Set storage set, bytes32 value) private view returns (bool) { - return set._indexes[value] != 0; - } - - /** - * @dev Returns the number of values on the set. O(1). - */ - function _length(Set storage set) private view returns (uint256) { - return set._values.length; - } - - /** - * @dev Returns the value stored at position `index` in the set. O(1). - * - * Note that there are no guarantees on the ordering of values inside the - * array, and it may change when more values are added or removed. - * - * Requirements: - * - * - `index` must be strictly less than {length}. - */ - function _at(Set storage set, uint256 index) private view returns (bytes32) { - return set._values[index]; - } - - /** - * @dev Return the entire set in an array - * - * WARNING: This operation will copy the entire storage to memory, which can be quite expensive. This is designed - * to mostly be used by view accessors that are queried without any gas fees. Developers should keep in mind that - * this function has an unbounded cost, and using it as part of a state-changing function may render the function - * uncallable if the set grows to a point where copying to memory consumes too much gas to fit in a block. - */ - function _values(Set storage set) private view returns (bytes32[] memory) { - return set._values; - } - - // Bytes32Set - - struct Bytes32Set { - Set _inner; - } - - /** - * @dev Add a value to a set. O(1). - * - * Returns true if the value was added to the set, that is if it was not - * already present. - */ - function add(Bytes32Set storage set, bytes32 value) internal returns (bool) { - return _add(set._inner, value); - } - - /** - * @dev Removes a value from a set. O(1). - * - * Returns true if the value was removed from the set, that is if it was - * present. - */ - function remove(Bytes32Set storage set, bytes32 value) internal returns (bool) { - return _remove(set._inner, value); - } - - /** - * @dev Returns true if the value is in the set. O(1). - */ - function contains(Bytes32Set storage set, bytes32 value) internal view returns (bool) { - return _contains(set._inner, value); - } - - /** - * @dev Returns the number of values in the set. O(1). - */ - function length(Bytes32Set storage set) internal view returns (uint256) { - return _length(set._inner); - } - - /** - * @dev Returns the value stored at position `index` in the set. O(1). - * - * Note that there are no guarantees on the ordering of values inside the - * array, and it may change when more values are added or removed. - * - * Requirements: - * - * - `index` must be strictly less than {length}. - */ - function at(Bytes32Set storage set, uint256 index) internal view returns (bytes32) { - return _at(set._inner, index); - } - - /** - * @dev Return the entire set in an array - * - * WARNING: This operation will copy the entire storage to memory, which can be quite expensive. This is designed - * to mostly be used by view accessors that are queried without any gas fees. Developers should keep in mind that - * this function has an unbounded cost, and using it as part of a state-changing function may render the function - * uncallable if the set grows to a point where copying to memory consumes too much gas to fit in a block. - */ - function values(Bytes32Set storage set) internal view returns (bytes32[] memory) { - return _values(set._inner); - } - - // AddressSet - - struct AddressSet { - Set _inner; - } - - /** - * @dev Add a value to a set. O(1). - * - * Returns true if the value was added to the set, that is if it was not - * already present. - */ - function add(AddressSet storage set, address value) internal returns (bool) { - return _add(set._inner, bytes32(uint256(uint160(value)))); - } - - /** - * @dev Removes a value from a set. O(1). - * - * Returns true if the value was removed from the set, that is if it was - * present. - */ - function remove(AddressSet storage set, address value) internal returns (bool) { - return _remove(set._inner, bytes32(uint256(uint160(value)))); - } - - /** - * @dev Returns true if the value is in the set. O(1). - */ - function contains(AddressSet storage set, address value) internal view returns (bool) { - return _contains(set._inner, bytes32(uint256(uint160(value)))); - } - - /** - * @dev Returns the number of values in the set. O(1). - */ - function length(AddressSet storage set) internal view returns (uint256) { - return _length(set._inner); - } - - /** - * @dev Returns the value stored at position `index` in the set. O(1). - * - * Note that there are no guarantees on the ordering of values inside the - * array, and it may change when more values are added or removed. - * - * Requirements: - * - * - `index` must be strictly less than {length}. - */ - function at(AddressSet storage set, uint256 index) internal view returns (address) { - return address(uint160(uint256(_at(set._inner, index)))); - } - - /** - * @dev Return the entire set in an array - * - * WARNING: This operation will copy the entire storage to memory, which can be quite expensive. This is designed - * to mostly be used by view accessors that are queried without any gas fees. Developers should keep in mind that - * this function has an unbounded cost, and using it as part of a state-changing function may render the function - * uncallable if the set grows to a point where copying to memory consumes too much gas to fit in a block. - */ - function values(AddressSet storage set) internal view returns (address[] memory) { - bytes32[] memory store = _values(set._inner); - address[] memory result; - - /// @solidity memory-safe-assembly - assembly { - result := store - } - - return result; - } - - // UintSet - - struct UintSet { - Set _inner; - } - - /** - * @dev Add a value to a set. O(1). - * - * Returns true if the value was added to the set, that is if it was not - * already present. - */ - function add(UintSet storage set, uint256 value) internal returns (bool) { - return _add(set._inner, bytes32(value)); - } - - /** - * @dev Removes a value from a set. O(1). - * - * Returns true if the value was removed from the set, that is if it was - * present. - */ - function remove(UintSet storage set, uint256 value) internal returns (bool) { - return _remove(set._inner, bytes32(value)); - } - - /** - * @dev Returns true if the value is in the set. O(1). - */ - function contains(UintSet storage set, uint256 value) internal view returns (bool) { - return _contains(set._inner, bytes32(value)); - } - - /** - * @dev Returns the number of values on the set. O(1). - */ - function length(UintSet storage set) internal view returns (uint256) { - return _length(set._inner); - } - - /** - * @dev Returns the value stored at position `index` in the set. O(1). - * - * Note that there are no guarantees on the ordering of values inside the - * array, and it may change when more values are added or removed. - * - * Requirements: - * - * - `index` must be strictly less than {length}. - */ - function at(UintSet storage set, uint256 index) internal view returns (uint256) { - return uint256(_at(set._inner, index)); - } - - /** - * @dev Return the entire set in an array - * - * WARNING: This operation will copy the entire storage to memory, which can be quite expensive. This is designed - * to mostly be used by view accessors that are queried without any gas fees. Developers should keep in mind that - * this function has an unbounded cost, and using it as part of a state-changing function may render the function - * uncallable if the set grows to a point where copying to memory consumes too much gas to fit in a block. - */ - function values(UintSet storage set) internal view returns (uint256[] memory) { - bytes32[] memory store = _values(set._inner); - uint256[] memory result; - - /// @solidity memory-safe-assembly - assembly { - result := store - } - - return result; - } -} - - -contract ActivityPool is Operator { - using SafeMath for uint256; - using SafeERC20 for IERC20; - using EnumerableSet for EnumerableSet.AddressSet; - using EnumerableSet for EnumerableSet.UintSet; - - event AddNewAct(uint256 id); - event Bet(address user, uint256 pID, uint256 bType, uint256 amount, uint256 time); - event SetPrize(uint256 pID, uint256 bType); - event Claim(address user, uint256 pID, uint256 bType, uint256 amount); - event RemovePeriodAct(uint256 pID); - - uint256 public constant muti = 1e18; - uint256 public periodID; - uint256 public betID; - - struct UserInfo { - address user; - uint256 pID; - uint256 amount; - uint256 betTime; - uint256 bType; - uint256 claimAmount; - } - - struct ActInfo { - string name; - string aName; - string bName; - address rewardToken; - uint256 startTime; - uint256 endTime; - uint256 minAmount; - uint256 maxAmount; - uint256 aAmount; - uint256 bAmount; - uint256 winType; - bool isBet; - } - - struct TimeInfo { - uint256 time; - uint256 aAmount; - uint256 bAmount; - } - - struct BestInfo { - address aUser; - address bUser; - uint256 aBet; - uint256 bBet; - } - - mapping(uint256 => BestInfo) bestInfo; - mapping(uint256 => uint256) public timeID; - mapping(uint256 => mapping(uint256 => TimeInfo)) public timeInfo; - mapping(address => mapping(uint256 => uint256)) public userBet; - mapping(uint256 => UserInfo) public betInfo; - mapping(uint256 => uint256) public perAmount; - mapping(uint256 => ActInfo) public actInfo; - mapping(uint256 => mapping(uint256 => string)) public descripName; - - mapping(address => EnumerableSet.UintSet) userPid; - mapping(uint256 => EnumerableSet.AddressSet) aUsers; - mapping(uint256 => EnumerableSet.AddressSet) bUsers; - EnumerableSet.UintSet activePeriod; - EnumerableSet.UintSet removePeriod; - - function addNewAct( - string memory name, - string memory aName, - string memory bName, - address token, - uint256 startTime, - uint256 endTime, - uint256 minAmount, - uint256 maxAmount - ) external onlyOperator { - - checkAdd(msg.sender, startTime, endTime, minAmount, maxAmount); - uint256 id = ++periodID; - actInfo[id].name = name; - actInfo[id].aName = aName; - actInfo[id].bName = bName; - actInfo[id].startTime = startTime; - actInfo[id].endTime = endTime; - actInfo[id].minAmount = minAmount; - actInfo[id].maxAmount = maxAmount; - actInfo[id].rewardToken = token; - descripName[id][1] = aName; - descripName[id][2] = bName; - activePeriod.add(id); - - emit AddNewAct(id); - } - - - function removePeriodAct(uint256 pID) external onlyOperator { - checkRemove(pID); - - activePeriod.remove(pID); - removePeriod.add(pID); - - emit RemovePeriodAct(pID); - } - - - function bet(uint256 pID, uint256 bType, uint256 amount) external payable { - checkBet(msg.sender, pID, bType, amount); - if(actInfo[pID].rewardToken == address(0)) { - require(msg.value == amount, "value err"); - } else { - require(msg.value == 0, "value amount err"); - } - - if(bType == 1) { - if(amount > bestInfo[pID].aBet) { - bestInfo[pID].aUser = msg.sender; - bestInfo[pID].aBet = amount; - } - } else { - if(amount > bestInfo[pID].bBet) { - bestInfo[pID].bUser = msg.sender; - bestInfo[pID].bBet = amount; - } - } - - userPid[msg.sender].add(pID); - uint256 id = ++betID; - userBet[msg.sender][pID] = id; - - if(bType == 1) { - aUsers[pID].add(msg.sender); - actInfo[pID].aAmount = actInfo[pID].aAmount.add(amount); - } else { - bUsers[pID].add(msg.sender); - actInfo[pID].bAmount = actInfo[pID].bAmount.add(amount); - } - - actInfo[pID].isBet = true; - betInfo[id].user = msg.sender; - betInfo[id].pID = pID; - betInfo[id].amount = amount; - betInfo[id].betTime = block.timestamp; - betInfo[id].bType = bType; - - uint256 tID = ++timeID[pID]; - timeInfo[pID][tID].time = block.timestamp; - timeInfo[pID][tID].aAmount = actInfo[pID].aAmount; - timeInfo[pID][tID].bAmount = actInfo[pID].bAmount; - - if(actInfo[pID].rewardToken != address(0)) { - IERC20(actInfo[pID].rewardToken).safeTransferFrom(msg.sender, address(this), amount); - } - emit Bet(msg.sender, pID, bType, amount, betInfo[id].betTime); - } - - function setPrize(uint256 pID, uint256 bType) external onlyOperator { - checkSetPrize(msg.sender, pID, bType); - - if(block.timestamp <= actInfo[pID].startTime) { - actInfo[pID].startTime = block.timestamp; - - } - actInfo[pID].endTime = block.timestamp; - - actInfo[pID].winType = bType; - perAmount[pID] = getPerAmount(pID, bType); - - emit SetPrize(pID, bType); - } - - function recive() public payable {} - - function claim(uint256 pID) external { - uint256 amount = checkClaim(msg.sender, pID); - - uint256 id = userBet[msg.sender][pID]; - betInfo[id].claimAmount = amount; - if(actInfo[pID].rewardToken != address(0)) { - IERC20(actInfo[pID].rewardToken).safeTransfer(msg.sender, amount); - } else { - payable(msg.sender).transfer(amount); - } - - emit Claim(msg.sender, pID, betInfo[id].bType, amount); - } - - function checkClaim(address user, uint256 pID) public view returns(uint256 amount) { - require(userPid[user].contains(pID), "not bet"); - uint256 id = userBet[user][pID]; - require(betInfo[id].user == user, "not user"); - require(actInfo[pID].winType != 0, "not prize"); - require(betInfo[id].claimAmount == 0, "has claim"); - - if(actInfo[pID].winType != 3) { - require(actInfo[pID].winType == betInfo[id].bType, "not right"); - amount = perAmount[pID].mul(betInfo[id].amount).div(muti); - require(amount > 0, "no amount"); - } else { - amount = betInfo[id].amount; - } - - return amount; - } - - function getActualRate( - address user, - uint256 pID, - uint256 bType, - uint256 amount - ) external view returns(uint256, uint256, bool) { - if(bType < 1 || bType > 2 || !activePeriod.contains(pID)) { - return (0, 0, false); - } else if(userBet[user][pID] != 0 || actInfo[pID].winType != 0 || amount == 0) { - (uint256 ra, uint256 rb) = getRate(pID, timeID[pID]); - return (ra, rb, false); - } else { - (uint256 aAmount, uint256 bAmount) = (actInfo[pID].aAmount, actInfo[pID].bAmount); - if(bType == 1) { - aAmount = aAmount.add(amount); - } else { - bAmount = bAmount.add(amount); - } - - uint256 total = aAmount.add(bAmount); - if(bAmount == 0 && aAmount != 0) { - return (muti, 0, true); - } - if(bAmount != 0 && aAmount == 0) { - return (0, muti, true); - } - return (total.mul(muti).div(aAmount), total.mul(muti).div(bAmount), true); - } - } - - function getRate(uint256 pID, uint256 tID) public view returns(uint256, uint256) { - (uint256 aAmount, uint256 bAmount) = (timeInfo[pID][tID].aAmount, timeInfo[pID][tID].bAmount); - uint256 total = aAmount.add(bAmount); - if(total == 0) { - return (0, 0); - } - if(bAmount == 0 && aAmount != 0) { - return (muti, 0); - } - if(bAmount != 0 && aAmount == 0) { - return (0, muti); - } - return (total.mul(muti).div(aAmount), total.mul(muti).div(bAmount)); - } - - function getBestInfo(uint256 pID) - external - view - returns(address aUser, address bUser, uint256 aBet, uint256 bBet, uint256 aReward, uint256 bReward) - { - aUser = bestInfo[pID].aUser; - bUser = bestInfo[pID].bUser; - aBet = bestInfo[pID].aBet; - bBet = bestInfo[pID].bBet; - aReward = getPerAmount(pID, 1).mul(aBet).div(muti); - bReward = getPerAmount(pID, 2).mul(bBet).div(muti); - } - - function getPerAmount(uint256 pID, uint256 bType) public view returns(uint256) { - uint256 total = actInfo[pID].aAmount.add(actInfo[pID].bAmount); - if(total == 0) { - return 0; - } - - if(actInfo[pID].winType == 3) { - return muti; - } - - if(bType == 1) { - if(actInfo[pID].aAmount == 0 || actInfo[pID].winType == 2) { - return 0; - } - return total.mul(muti).div(actInfo[pID].aAmount); - } - - if(bType == 2) { - if(actInfo[pID].bAmount == 0 || actInfo[pID].winType == 1) { - return 0; - } - return total.mul(muti).div(actInfo[pID].bAmount); - } - - return 0; - - } - - function checkSetPrize(address user, uint256 pID, uint256 bType) public view returns(bool) { - require(user == owner() || user == operator, "no permission"); - require(bType > 0 && bType <= 3, "type err"); - require(activePeriod.contains(pID), "not active"); - require(actInfo[pID].winType == 0, "has set"); - - return true; - } - - function checkBet( - address user, - uint256 pID, - uint256 bType, - uint256 amount - ) public view returns(bool) { - require(activePeriod.contains(pID), "not active"); - require(actInfo[pID].startTime <= block.timestamp, "not start"); - require(actInfo[pID].endTime > block.timestamp, "has end"); - require(!userPid[user].contains(pID), "has bet"); - require(bType > 0 && bType < 3, "type err"); - require(amount >= actInfo[pID].minAmount && amount <= actInfo[pID].maxAmount, "amount err"); - if(actInfo[pID].rewardToken != address(0)) { - require(IERC20(actInfo[pID].rewardToken).allowance(user, address(this)) >= amount, "not approve enough"); - require(IERC20(actInfo[pID].rewardToken).balanceOf(user) >= amount, "not enough"); - } else { - require(user.balance >= amount, "main token err"); - } - - return true; - } - - - function checkRemove(uint256 pID) public view returns(bool) { - require(activePeriod.contains(pID), "not in"); - require(!actInfo[pID].isBet, "has bet"); - - return true; - } - - function checkAdd( - address user, - uint256 startTime, - uint256 endTime, - uint256 minAmount, - uint256 maxAmount - ) public view returns(bool) { - require(user == owner() || user == operator, "no permission"); - require(startTime > block.timestamp, "startTime err"); - require(endTime > startTime, "endTime err"); - require(minAmount > 0 && maxAmount > minAmount, "amount err"); - - return true; - } - - function getStatus(uint256 pID) external view returns(uint256) { - if(!removePeriod.contains(pID) && !activePeriod.contains(pID)) { - return 5; - } else if(removePeriod.contains(pID)) { - return 6; - } else if(block.timestamp < actInfo[pID].startTime) { - return 1; - } else if ( - actInfo[pID].startTime <= block.timestamp && - actInfo[pID].endTime > block.timestamp - ) { - return 2; - } else if (actInfo[pID].endTime <= block.timestamp && actInfo[pID].winType == 0){ - return 3; - } else if(actInfo[pID].winType != 0) { - return 4; - } - return 0; - } - - function getUserPidNum(address user) external view returns(uint256) { - return userPid[user].length(); - } - - function getUserPid(address user, uint256 index) external view returns(uint256) { - return userPid[user].at(index); - } - - function getAUsersNum(uint256 pID) external view returns(uint256) { - return aUsers[pID].length(); - } - - function getAUsers(uint256 pID, uint256 index) external view returns(address) { - return aUsers[pID].at(index); - } - - function getBUsersNum(uint256 pID) external view returns(uint256) { - return bUsers[pID].length(); - } - - function getBUsers(uint256 pID, uint256 index) external view returns(address) { - return bUsers[pID].at(index); - } - - function getActivePeriodNum() external view returns(uint256) { - return activePeriod.length(); - } - - function getActivePeriod(uint256 index) external view returns(uint256) { - return activePeriod.at(index); - } - - function getRemovePeriodNum() external view returns(uint256) { - return removePeriod.length(); - } - - function getRemovePeriod(uint256 index) external view returns(uint256) { - return removePeriod.at(index); - } -} \ No newline at end of file diff --git a/app/api/uploads/ActivityPool-1729808507370-473274218.sol b/app/api/uploads/ActivityPool-1729808507370-473274218.sol deleted file mode 100644 index daf3372..0000000 --- a/app/api/uploads/ActivityPool-1729808507370-473274218.sol +++ /dev/null @@ -1,1648 +0,0 @@ -// SPDX-License-Identifier: MIT -// OpenZeppelin Contracts (last updated v4.7.0) (utils/Address.sol) - -pragma solidity ^0.8.1; - -/** - * @dev Collection of functions related to the address type - */ -library Address { - /** - * @dev Returns true if `account` is a contract. - * - * [IMPORTANT] - * ==== - * It is unsafe to assume that an address for which this function returns - * false is an externally-owned account (EOA) and not a contract. - * - * Among others, `isContract` will return false for the following - * types of addresses: - * - * - an externally-owned account - * - a contract in construction - * - an address where a contract will be created - * - an address where a contract lived, but was destroyed - * ==== - * - * [IMPORTANT] - * ==== - * You shouldn't rely on `isContract` to protect against flash loan attacks! - * - * Preventing calls from contracts is highly discouraged. It breaks composability, breaks support for smart wallets - * like Gnosis Safe, and does not provide security since it can be circumvented by calling from a contract - * constructor. - * ==== - */ - function isContract(address account) internal view returns (bool) { - // This method relies on extcodesize/address.code.length, which returns 0 - // for contracts in construction, since the code is only stored at the end - // of the constructor execution. - - return account.code.length > 0; - } - - /** - * @dev Replacement for Solidity's `transfer`: sends `amount` wei to - * `recipient`, forwarding all available gas and reverting on errors. - * - * https://eips.ethereum.org/EIPS/eip-1884[EIP1884] increases the gas cost - * of certain opcodes, possibly making contracts go over the 2300 gas limit - * imposed by `transfer`, making them unable to receive funds via - * `transfer`. {sendValue} removes this limitation. - * - * https://diligence.consensys.net/posts/2019/09/stop-using-soliditys-transfer-now/[Learn more]. - * - * IMPORTANT: because control is transferred to `recipient`, care must be - * taken to not create reentrancy vulnerabilities. Consider using - * {ReentrancyGuard} or the - * https://solidity.readthedocs.io/en/v0.5.11/security-considerations.html#use-the-checks-effects-interactions-pattern[checks-effects-interactions pattern]. - */ - function sendValue(address payable recipient, uint256 amount) internal { - require(address(this).balance >= amount, "Address: insufficient balance"); - - (bool success, ) = recipient.call{value: amount}(""); - require(success, "Address: unable to send value, recipient may have reverted"); - } - - /** - * @dev Performs a Solidity function call using a low level `call`. A - * plain `call` is an unsafe replacement for a function call: use this - * function instead. - * - * If `target` reverts with a revert reason, it is bubbled up by this - * function (like regular Solidity function calls). - * - * Returns the raw returned data. To convert to the expected return value, - * use https://solidity.readthedocs.io/en/latest/units-and-global-variables.html?highlight=abi.decode#abi-encoding-and-decoding-functions[`abi.decode`]. - * - * Requirements: - * - * - `target` must be a contract. - * - calling `target` with `data` must not revert. - * - * _Available since v3.1._ - */ - function functionCall(address target, bytes memory data) internal returns (bytes memory) { - return functionCallWithValue(target, data, 0, "Address: low-level call failed"); - } - - /** - * @dev Same as {xref-Address-functionCall-address-bytes-}[`functionCall`], but with - * `errorMessage` as a fallback revert reason when `target` reverts. - * - * _Available since v3.1._ - */ - function functionCall( - address target, - bytes memory data, - string memory errorMessage - ) internal returns (bytes memory) { - return functionCallWithValue(target, data, 0, errorMessage); - } - - /** - * @dev Same as {xref-Address-functionCall-address-bytes-}[`functionCall`], - * but also transferring `value` wei to `target`. - * - * Requirements: - * - * - the calling contract must have an ETH balance of at least `value`. - * - the called Solidity function must be `payable`. - * - * _Available since v3.1._ - */ - function functionCallWithValue( - address target, - bytes memory data, - uint256 value - ) internal returns (bytes memory) { - return functionCallWithValue(target, data, value, "Address: low-level call with value failed"); - } - - /** - * @dev Same as {xref-Address-functionCallWithValue-address-bytes-uint256-}[`functionCallWithValue`], but - * with `errorMessage` as a fallback revert reason when `target` reverts. - * - * _Available since v3.1._ - */ - function functionCallWithValue( - address target, - bytes memory data, - uint256 value, - string memory errorMessage - ) internal returns (bytes memory) { - require(address(this).balance >= value, "Address: insufficient balance for call"); - (bool success, bytes memory returndata) = target.call{value: value}(data); - return verifyCallResultFromTarget(target, success, returndata, errorMessage); - } - - /** - * @dev Same as {xref-Address-functionCall-address-bytes-}[`functionCall`], - * but performing a static call. - * - * _Available since v3.3._ - */ - function functionStaticCall(address target, bytes memory data) internal view returns (bytes memory) { - return functionStaticCall(target, data, "Address: low-level static call failed"); - } - - /** - * @dev Same as {xref-Address-functionCall-address-bytes-string-}[`functionCall`], - * but performing a static call. - * - * _Available since v3.3._ - */ - function functionStaticCall( - address target, - bytes memory data, - string memory errorMessage - ) internal view returns (bytes memory) { - (bool success, bytes memory returndata) = target.staticcall(data); - return verifyCallResultFromTarget(target, success, returndata, errorMessage); - } - - /** - * @dev Same as {xref-Address-functionCall-address-bytes-}[`functionCall`], - * but performing a delegate call. - * - * _Available since v3.4._ - */ - function functionDelegateCall(address target, bytes memory data) internal returns (bytes memory) { - return functionDelegateCall(target, data, "Address: low-level delegate call failed"); - } - - /** - * @dev Same as {xref-Address-functionCall-address-bytes-string-}[`functionCall`], - * but performing a delegate call. - * - * _Available since v3.4._ - */ - function functionDelegateCall( - address target, - bytes memory data, - string memory errorMessage - ) internal returns (bytes memory) { - (bool success, bytes memory returndata) = target.delegatecall(data); - return verifyCallResultFromTarget(target, success, returndata, errorMessage); - } - - /** - * @dev Tool to verify that a low level call to smart-contract was successful, and revert (either by bubbling - * the revert reason or using the provided one) in case of unsuccessful call or if target was not a contract. - * - * _Available since v4.8._ - */ - function verifyCallResultFromTarget( - address target, - bool success, - bytes memory returndata, - string memory errorMessage - ) internal view returns (bytes memory) { - if (success) { - if (returndata.length == 0) { - // only check isContract if the call was successful and the return data is empty - // otherwise we already know that it was a contract - require(isContract(target), "Address: call to non-contract"); - } - return returndata; - } else { - _revert(returndata, errorMessage); - } - } - - /** - * @dev Tool to verify that a low level call was successful, and revert if it wasn't, either by bubbling the - * revert reason or using the provided one. - * - * _Available since v4.3._ - */ - function verifyCallResult( - bool success, - bytes memory returndata, - string memory errorMessage - ) internal pure returns (bytes memory) { - if (success) { - return returndata; - } else { - _revert(returndata, errorMessage); - } - } - - function _revert(bytes memory returndata, string memory errorMessage) private pure { - // Look for revert reason and bubble it up if present - if (returndata.length > 0) { - // The easiest way to bubble the revert reason is using memory via assembly - /// @solidity memory-safe-assembly - assembly { - let returndata_size := mload(returndata) - revert(add(32, returndata), returndata_size) - } - } else { - revert(errorMessage); - } - } -} - -// OpenZeppelin Contracts (last updated v4.6.0) (token/ERC20/IERC20.sol) - - - -/** - * @dev Interface of the ERC20 standard as defined in the EIP. - */ -interface IERC20 { - /** - * @dev Emitted when `value` tokens are moved from one account (`from`) to - * another (`to`). - * - * Note that `value` may be zero. - */ - event Transfer(address indexed from, address indexed to, uint256 value); - - /** - * @dev Emitted when the allowance of a `spender` for an `owner` is set by - * a call to {approve}. `value` is the new allowance. - */ - event Approval(address indexed owner, address indexed spender, uint256 value); - - /** - * @dev Returns the amount of tokens in existence. - */ - function totalSupply() external view returns (uint256); - - /** - * @dev Returns the amount of tokens owned by `account`. - */ - function balanceOf(address account) external view returns (uint256); - - /** - * @dev Moves `amount` tokens from the caller's account to `to`. - * - * Returns a boolean value indicating whether the operation succeeded. - * - * Emits a {Transfer} event. - */ - function transfer(address to, uint256 amount) external returns (bool); - - /** - * @dev Returns the remaining number of tokens that `spender` will be - * allowed to spend on behalf of `owner` through {transferFrom}. This is - * zero by default. - * - * This value changes when {approve} or {transferFrom} are called. - */ - function allowance(address owner, address spender) external view returns (uint256); - - /** - * @dev Sets `amount` as the allowance of `spender` over the caller's tokens. - * - * Returns a boolean value indicating whether the operation succeeded. - * - * IMPORTANT: Beware that changing an allowance with this method brings the risk - * that someone may use both the old and the new allowance by unfortunate - * transaction ordering. One possible solution to mitigate this race - * condition is to first reduce the spender's allowance to 0 and set the - * desired value afterwards: - * https://github.com/ethereum/EIPs/issues/20#issuecomment-263524729 - * - * Emits an {Approval} event. - */ - function approve(address spender, uint256 amount) external returns (bool); - - /** - * @dev Moves `amount` tokens from `from` to `to` using the - * allowance mechanism. `amount` is then deducted from the caller's - * allowance. - * - * Returns a boolean value indicating whether the operation succeeded. - * - * Emits a {Transfer} event. - */ - function transferFrom( - address from, - address to, - uint256 amount - ) external returns (bool); - - - function mint(address account_, uint256 amount_) external; - - function burn(uint256 amount) external; - -} - - - - - - - - - - - -/** - * @dev Wrappers over Solidity's arithmetic operations with added overflow - * checks. - * - * Arithmetic operations in Solidity wrap on overflow. This can easily result - * in bugs, because programmers usually assume that an overflow raises an - * error, which is the standard behavior in high level programming languages. - * `SafeMath` restores this intuition by reverting the transaction when an - * operation overflows. - * - * Using this library instead of the unchecked operations eliminates an entire - * class of bugs, so it's recommended to use it always. - */ -library SafeMath { - /** - * @dev Returns the addition of two unsigned integers, reverting on - * overflow. - * - * Counterpart to Solidity's `+` operator. - * - * Requirements: - * - * - Addition cannot overflow. - */ - function add(uint256 a, uint256 b) internal pure returns (uint256) { - uint256 c = a + b; - require(c >= a, "SafeMath: addition overflow"); - - return c; - } - - /** - * @dev Returns the subtraction of two unsigned integers, reverting on - * overflow (when the result is negative). - * - * Counterpart to Solidity's `-` operator. - * - * Requirements: - * - * - Subtraction cannot overflow. - */ - function sub(uint256 a, uint256 b) internal pure returns (uint256) { - return sub(a, b, "SafeMath: subtraction overflow"); - } - - /** - * @dev Returns the subtraction of two unsigned integers, reverting with custom message on - * overflow (when the result is negative). - * - * Counterpart to Solidity's `-` operator. - * - * Requirements: - * - * - Subtraction cannot overflow. - */ - function sub( - uint256 a, - uint256 b, - string memory errorMessage - ) internal pure returns (uint256) { - require(b <= a, errorMessage); - uint256 c = a - b; - - return c; - } - - /** - * @dev Returns the multiplication of two unsigned integers, reverting on - * overflow. - * - * Counterpart to Solidity's `*` operator. - * - * Requirements: - * - * - Multiplication cannot overflow. - */ - function mul(uint256 a, uint256 b) internal pure returns (uint256) { - // Gas optimization: this is cheaper than requiring 'a' not being zero, but the - // benefit is lost if 'b' is also tested. - // See: https://github.com/OpenZeppelin/openzeppelin-contracts/pull/522 - if (a == 0) { - return 0; - } - - uint256 c = a * b; - require(c / a == b, "SafeMath: multiplication overflow"); - - return c; - } - - /** - * @dev Returns the integer division of two unsigned integers. Reverts on - * division by zero. The result is rounded towards zero. - * - * Counterpart to Solidity's `/` operator. Note: this function uses a - * `revert` opcode (which leaves remaining gas untouched) while Solidity - * uses an invalid opcode to revert (consuming all remaining gas). - * - * Requirements: - * - * - The divisor cannot be zero. - */ - function div(uint256 a, uint256 b) internal pure returns (uint256) { - return div(a, b, "SafeMath: division by zero"); - } - - /** - * @dev Returns the integer division of two unsigned integers. Reverts with custom message on - * division by zero. The result is rounded towards zero. - * - * Counterpart to Solidity's `/` operator. Note: this function uses a - * `revert` opcode (which leaves remaining gas untouched) while Solidity - * uses an invalid opcode to revert (consuming all remaining gas). - * - * Requirements: - * - * - The divisor cannot be zero. - */ - function div( - uint256 a, - uint256 b, - string memory errorMessage - ) internal pure returns (uint256) { - require(b > 0, errorMessage); - uint256 c = a / b; - // assert(a == b * c + a % b); // There is no case in which this doesn't hold - - return c; - } - - /** - * @dev Returns the remainder of dividing two unsigned integers. (unsigned integer modulo), - * Reverts when dividing by zero. - * - * Counterpart to Solidity's `%` operator. This function uses a `revert` - * opcode (which leaves remaining gas untouched) while Solidity uses an - * invalid opcode to revert (consuming all remaining gas). - * - * Requirements: - * - * - The divisor cannot be zero. - */ - function mod(uint256 a, uint256 b) internal pure returns (uint256) { - return mod(a, b, "SafeMath: modulo by zero"); - } - - /** - * @dev Returns the remainder of dividing two unsigned integers. (unsigned integer modulo), - * Reverts with custom message when dividing by zero. - * - * Counterpart to Solidity's `%` operator. This function uses a `revert` - * opcode (which leaves remaining gas untouched) while Solidity uses an - * invalid opcode to revert (consuming all remaining gas). - * - * Requirements: - * - * - The divisor cannot be zero. - */ - function mod( - uint256 a, - uint256 b, - string memory errorMessage - ) internal pure returns (uint256) { - require(b != 0, errorMessage); - return a % b; - } - - // babylonian method (https://en.wikipedia.org/wiki/Methods_of_computing_square_roots#Babylonian_method) - function sqrrt(uint256 a) internal pure returns (uint256 c) { - if (a > 3) { - c = a; - uint256 b = add(div(a, 2), 1); - while (b < c) { - c = b; - b = div(add(div(a, b), b), 2); - } - } else if (a != 0) { - c = 1; - } - } - - /* - * Expects percentage to be trailed by 00, - */ - function percentageAmount(uint256 total_, uint8 percentage_) internal pure returns (uint256 percentAmount_) { - return div(mul(total_, percentage_), 1000); - } - - /* - * Expects percentage to be trailed by 00, - */ - function substractPercentage(uint256 total_, uint8 percentageToSub_) internal pure returns (uint256 result_) { - return sub(total_, div(mul(total_, percentageToSub_), 1000)); - } - - function percentageOfTotal(uint256 part_, uint256 total_) internal pure returns (uint256 percent_) { - return div(mul(part_, 100), total_); - } - - /** - * Taken from Hypersonic https://github.com/M2629/HyperSonic/blob/main/Math.sol - * @dev Returns the average of two numbers. The result is rounded towards - * zero. - */ - function average(uint256 a, uint256 b) internal pure returns (uint256) { - // (a + b) / 2 can overflow, so we distribute - return (a / 2) + (b / 2) + (((a % 2) + (b % 2)) / 2); - } - - function quadraticPricing(uint256 payment_, uint256 multiplier_) internal pure returns (uint256) { - return sqrrt(mul(multiplier_, payment_)); - } - - function bondingCurve(uint256 supply_, uint256 multiplier_) internal pure returns (uint256) { - return mul(multiplier_, supply_); - } -} - -// OpenZeppelin Contracts (last updated v4.7.0) (token/ERC20/utils/SafeERC20.sol) - - - - - -// OpenZeppelin Contracts v4.4.1 (token/ERC20/extensions/draft-IERC20Permit.sol) - - - -/** - * @dev Interface of the ERC20 Permit extension allowing approvals to be made via signatures, as defined in - * https://eips.ethereum.org/EIPS/eip-2612[EIP-2612]. - * - * Adds the {permit} method, which can be used to change an account's ERC20 allowance (see {IERC20-allowance}) by - * presenting a message signed by the account. By not relying on {IERC20-approve}, the token holder account doesn't - * need to send a transaction, and thus is not required to hold Ether at all. - */ -interface IERC20Permit { - /** - * @dev Sets `value` as the allowance of `spender` over ``owner``'s tokens, - * given ``owner``'s signed approval. - * - * IMPORTANT: The same issues {IERC20-approve} has related to transaction - * ordering also apply here. - * - * Emits an {Approval} event. - * - * Requirements: - * - * - `spender` cannot be the zero address. - * - `deadline` must be a timestamp in the future. - * - `v`, `r` and `s` must be a valid `secp256k1` signature from `owner` - * over the EIP712-formatted function arguments. - * - the signature must use ``owner``'s current nonce (see {nonces}). - * - * For more information on the signature format, see the - * https://eips.ethereum.org/EIPS/eip-2612#specification[relevant EIP - * section]. - */ - function permit( - address owner, - address spender, - uint256 value, - uint256 deadline, - uint8 v, - bytes32 r, - bytes32 s - ) external; - - /** - * @dev Returns the current nonce for `owner`. This value must be - * included whenever a signature is generated for {permit}. - * - * Every successful call to {permit} increases ``owner``'s nonce by one. This - * prevents a signature from being used multiple times. - */ - function nonces(address owner) external view returns (uint256); - - /** - * @dev Returns the domain separator used in the encoding of the signature for {permit}, as defined by {EIP712}. - */ - // solhint-disable-next-line func-name-mixedcase - function DOMAIN_SEPARATOR() external view returns (bytes32); -} - - - -/** - * @title SafeERC20 - * @dev Wrappers around ERC20 operations that throw on failure (when the token - * contract returns false). Tokens that return no value (and instead revert or - * throw on failure) are also supported, non-reverting calls are assumed to be - * successful. - * To use this library you can add a `using SafeERC20 for IERC20;` statement to your contract, - * which allows you to call the safe operations as `token.safeTransfer(...)`, etc. - */ -library SafeERC20 { - using Address for address; - - function safeTransfer( - IERC20 token, - address to, - uint256 value - ) internal { - _callOptionalReturn(token, abi.encodeWithSelector(token.transfer.selector, to, value)); - } - - function safeTransferFrom( - IERC20 token, - address from, - address to, - uint256 value - ) internal { - _callOptionalReturn(token, abi.encodeWithSelector(token.transferFrom.selector, from, to, value)); - } - - /** - * @dev Deprecated. This function has issues similar to the ones found in - * {IERC20-approve}, and its usage is discouraged. - * - * Whenever possible, use {safeIncreaseAllowance} and - * {safeDecreaseAllowance} instead. - */ - function safeApprove( - IERC20 token, - address spender, - uint256 value - ) internal { - // safeApprove should only be called when setting an initial allowance, - // or when resetting it to zero. To increase and decrease it, use - // 'safeIncreaseAllowance' and 'safeDecreaseAllowance' - require( - (value == 0) || (token.allowance(address(this), spender) == 0), - "SafeERC20: approve from non-zero to non-zero allowance" - ); - _callOptionalReturn(token, abi.encodeWithSelector(token.approve.selector, spender, value)); - } - - function safeIncreaseAllowance( - IERC20 token, - address spender, - uint256 value - ) internal { - uint256 newAllowance = token.allowance(address(this), spender) + value; - _callOptionalReturn(token, abi.encodeWithSelector(token.approve.selector, spender, newAllowance)); - } - - function safeDecreaseAllowance( - IERC20 token, - address spender, - uint256 value - ) internal { - unchecked { - uint256 oldAllowance = token.allowance(address(this), spender); - require(oldAllowance >= value, "SafeERC20: decreased allowance below zero"); - uint256 newAllowance = oldAllowance - value; - _callOptionalReturn(token, abi.encodeWithSelector(token.approve.selector, spender, newAllowance)); - } - } - - function safePermit( - IERC20Permit token, - address owner, - address spender, - uint256 value, - uint256 deadline, - uint8 v, - bytes32 r, - bytes32 s - ) internal { - uint256 nonceBefore = token.nonces(owner); - token.permit(owner, spender, value, deadline, v, r, s); - uint256 nonceAfter = token.nonces(owner); - require(nonceAfter == nonceBefore + 1, "SafeERC20: permit did not succeed"); - } - - /** - * @dev Imitates a Solidity high-level call (i.e. a regular function call to a contract), relaxing the requirement - * on the return value: the return value is optional (but if data is returned, it must not be false). - * @param token The token targeted by the call. - * @param data The call data (encoded using abi.encode or one of its variants). - */ - function _callOptionalReturn(IERC20 token, bytes memory data) private { - // We need to perform a low level call here, to bypass Solidity's return data size checking mechanism, since - // we're implementing it ourselves. We use {Address.functionCall} to perform this call, which verifies that - // the target address contains contract code and also asserts for success in the low-level call. - - bytes memory returndata = address(token).functionCall(data, "SafeERC20: low-level call failed"); - if (returndata.length > 0) { - // Return data is optional - require(abi.decode(returndata, (bool)), "SafeERC20: ERC20 operation did not succeed"); - } - } -} - - - - - - - - - - - - - - -/** - * @dev Provides information about the current execution context, including the - * sender of the transaction and its data. While these are generally available - * via msg.sender and msg.data, they should not be accessed in such a direct - * manner, since when dealing with meta-transactions the account sending and - * paying for execution may not be the actual sender (as far as an application - * is concerned). - * - * This contract is only required for intermediate, library-like contracts. - */ -abstract contract Context { - function _msgSender() internal view virtual returns (address) { - return msg.sender; - } - - function _msgData() internal view virtual returns (bytes calldata) { - return msg.data; - } -} - - -/** - * @dev Contract module which provides a basic access control mechanism, where - * there is an account (an owner) that can be granted exclusive access to - * specific functions. - * - * By default, the owner account will be the one that deploys the contract. This - * can later be changed with {transferOwnership}. - * - * This module is used through inheritance. It will make available the modifier - * `onlyOwner`, which can be applied to your functions to restrict their use to - * the owner. - */ -abstract contract Ownable is Context { - address private _owner; - - event OwnershipTransferred(address indexed previousOwner, address indexed newOwner); - - /** - * @dev Initializes the contract setting the deployer as the initial owner. - */ - constructor() { - _transferOwnership(_msgSender()); - } - - /** - * @dev Throws if called by any account other than the owner. - */ - modifier onlyOwner() { - _checkOwner(); - _; - } - - /** - * @dev Returns the address of the current owner. - */ - function owner() public view virtual returns (address) { - return _owner; - } - - /** - * @dev Throws if the sender is not the owner. - */ - function _checkOwner() internal view virtual { - require(owner() == _msgSender(), "Ownable: caller is not the owner"); - } - - /** - * @dev Leaves the contract without owner. It will not be possible to call - * `onlyOwner` functions anymore. Can only be called by the current owner. - * - * NOTE: Renouncing ownership will leave the contract without an owner, - * thereby removing any functionality that is only available to the owner. - */ - function renounceOwnership() public virtual onlyOwner { - _transferOwnership(address(0)); - } - - /** - * @dev Transfers ownership of the contract to a new account (`newOwner`). - * Can only be called by the current owner. - */ - function transferOwnership(address newOwner) public virtual onlyOwner { - require(newOwner != address(0), "Ownable: new owner is the zero address"); - _transferOwnership(newOwner); - } - - /** - * @dev Transfers ownership of the contract to a new account (`newOwner`). - * Internal function without access restriction. - */ - function _transferOwnership(address newOwner) internal virtual { - address oldOwner = _owner; - _owner = newOwner; - emit OwnershipTransferred(oldOwner, newOwner); - } -} - - -contract Operator is Ownable { - address public operator; - uint256 constant baseRate = 10000; - - modifier onlyOperator { - require(msg.sender == owner() || msg.sender == operator, "no permission"); - _; - } - - function setOperator(address operator_) external onlyOwner { - operator = operator_; - } - - - function getCurrTime() external view returns(uint256) { - return block.timestamp; - } - - function getBlockNum() external view returns(uint256) { - return block.number; - } - -} - - - - - -/** - * @dev Library for managing - * https://en.wikipedia.org/wiki/Set_(abstract_data_type)[sets] of primitive - * types. - * - * Sets have the following properties: - * - * - Elements are added, removed, and checked for existence in constant time - * (O(1)). - * - Elements are enumerated in O(n). No guarantees are made on the ordering. - * - * ``` - * contract Example { - * // Add the library methods - * using EnumerableSet for EnumerableSet.AddressSet; - * - * // Declare a set state variable - * EnumerableSet.AddressSet private mySet; - * } - * ``` - * - * As of v3.3.0, sets of type `bytes32` (`Bytes32Set`), `address` (`AddressSet`) - * and `uint256` (`UintSet`) are supported. - * - * [WARNING] - * ==== - * Trying to delete such a structure from storage will likely result in data corruption, rendering the structure unusable. - * See https://github.com/ethereum/solidity/pull/11843[ethereum/solidity#11843] for more info. - * - * In order to clean an EnumerableSet, you can either remove all elements one by one or create a fresh instance using an array of EnumerableSet. - * ==== - */ - -library EnumerableSet { - // To implement this library for multiple types with as little code - // repetition as possible, we write it in terms of a generic Set type with - // bytes32 values. - // The Set implementation uses private functions, and user-facing - // implementations (such as AddressSet) are just wrappers around the - // underlying Set. - // This means that we can only create new EnumerableSets for types that fit - // in bytes32. - - struct Set { - // Storage of set values - bytes32[] _values; - // Position of the value in the `values` array, plus 1 because index 0 - // means a value is not in the set. - mapping(bytes32 => uint256) _indexes; - } - - /** - * @dev Add a value to a set. O(1). - * - * Returns true if the value was added to the set, that is if it was not - * already present. - */ - function _add(Set storage set, bytes32 value) private returns (bool) { - if (!_contains(set, value)) { - set._values.push(value); - // The value is stored at length-1, but we add 1 to all indexes - // and use 0 as a sentinel value - set._indexes[value] = set._values.length; - return true; - } else { - return false; - } - } - - /** - * @dev Removes a value from a set. O(1). - * - * Returns true if the value was removed from the set, that is if it was - * present. - */ - function _remove(Set storage set, bytes32 value) private returns (bool) { - // We read and store the value's index to prevent multiple reads from the same storage slot - uint256 valueIndex = set._indexes[value]; - - if (valueIndex != 0) { - // Equivalent to contains(set, value) - // To delete an element from the _values array in O(1), we swap the element to delete with the last one in - // the array, and then remove the last element (sometimes called as 'swap and pop'). - // This modifies the order of the array, as noted in {at}. - - uint256 toDeleteIndex = valueIndex - 1; - uint256 lastIndex = set._values.length - 1; - - if (lastIndex != toDeleteIndex) { - bytes32 lastValue = set._values[lastIndex]; - - // Move the last value to the index where the value to delete is - set._values[toDeleteIndex] = lastValue; - // Update the index for the moved value - set._indexes[lastValue] = valueIndex; // Replace lastValue's index to valueIndex - } - - // Delete the slot where the moved value was stored - set._values.pop(); - - // Delete the index for the deleted slot - delete set._indexes[value]; - - return true; - } else { - return false; - } - } - - /** - * @dev Returns true if the value is in the set. O(1). - */ - function _contains(Set storage set, bytes32 value) private view returns (bool) { - return set._indexes[value] != 0; - } - - /** - * @dev Returns the number of values on the set. O(1). - */ - function _length(Set storage set) private view returns (uint256) { - return set._values.length; - } - - /** - * @dev Returns the value stored at position `index` in the set. O(1). - * - * Note that there are no guarantees on the ordering of values inside the - * array, and it may change when more values are added or removed. - * - * Requirements: - * - * - `index` must be strictly less than {length}. - */ - function _at(Set storage set, uint256 index) private view returns (bytes32) { - return set._values[index]; - } - - /** - * @dev Return the entire set in an array - * - * WARNING: This operation will copy the entire storage to memory, which can be quite expensive. This is designed - * to mostly be used by view accessors that are queried without any gas fees. Developers should keep in mind that - * this function has an unbounded cost, and using it as part of a state-changing function may render the function - * uncallable if the set grows to a point where copying to memory consumes too much gas to fit in a block. - */ - function _values(Set storage set) private view returns (bytes32[] memory) { - return set._values; - } - - // Bytes32Set - - struct Bytes32Set { - Set _inner; - } - - /** - * @dev Add a value to a set. O(1). - * - * Returns true if the value was added to the set, that is if it was not - * already present. - */ - function add(Bytes32Set storage set, bytes32 value) internal returns (bool) { - return _add(set._inner, value); - } - - /** - * @dev Removes a value from a set. O(1). - * - * Returns true if the value was removed from the set, that is if it was - * present. - */ - function remove(Bytes32Set storage set, bytes32 value) internal returns (bool) { - return _remove(set._inner, value); - } - - /** - * @dev Returns true if the value is in the set. O(1). - */ - function contains(Bytes32Set storage set, bytes32 value) internal view returns (bool) { - return _contains(set._inner, value); - } - - /** - * @dev Returns the number of values in the set. O(1). - */ - function length(Bytes32Set storage set) internal view returns (uint256) { - return _length(set._inner); - } - - /** - * @dev Returns the value stored at position `index` in the set. O(1). - * - * Note that there are no guarantees on the ordering of values inside the - * array, and it may change when more values are added or removed. - * - * Requirements: - * - * - `index` must be strictly less than {length}. - */ - function at(Bytes32Set storage set, uint256 index) internal view returns (bytes32) { - return _at(set._inner, index); - } - - /** - * @dev Return the entire set in an array - * - * WARNING: This operation will copy the entire storage to memory, which can be quite expensive. This is designed - * to mostly be used by view accessors that are queried without any gas fees. Developers should keep in mind that - * this function has an unbounded cost, and using it as part of a state-changing function may render the function - * uncallable if the set grows to a point where copying to memory consumes too much gas to fit in a block. - */ - function values(Bytes32Set storage set) internal view returns (bytes32[] memory) { - return _values(set._inner); - } - - // AddressSet - - struct AddressSet { - Set _inner; - } - - /** - * @dev Add a value to a set. O(1). - * - * Returns true if the value was added to the set, that is if it was not - * already present. - */ - function add(AddressSet storage set, address value) internal returns (bool) { - return _add(set._inner, bytes32(uint256(uint160(value)))); - } - - /** - * @dev Removes a value from a set. O(1). - * - * Returns true if the value was removed from the set, that is if it was - * present. - */ - function remove(AddressSet storage set, address value) internal returns (bool) { - return _remove(set._inner, bytes32(uint256(uint160(value)))); - } - - /** - * @dev Returns true if the value is in the set. O(1). - */ - function contains(AddressSet storage set, address value) internal view returns (bool) { - return _contains(set._inner, bytes32(uint256(uint160(value)))); - } - - /** - * @dev Returns the number of values in the set. O(1). - */ - function length(AddressSet storage set) internal view returns (uint256) { - return _length(set._inner); - } - - /** - * @dev Returns the value stored at position `index` in the set. O(1). - * - * Note that there are no guarantees on the ordering of values inside the - * array, and it may change when more values are added or removed. - * - * Requirements: - * - * - `index` must be strictly less than {length}. - */ - function at(AddressSet storage set, uint256 index) internal view returns (address) { - return address(uint160(uint256(_at(set._inner, index)))); - } - - /** - * @dev Return the entire set in an array - * - * WARNING: This operation will copy the entire storage to memory, which can be quite expensive. This is designed - * to mostly be used by view accessors that are queried without any gas fees. Developers should keep in mind that - * this function has an unbounded cost, and using it as part of a state-changing function may render the function - * uncallable if the set grows to a point where copying to memory consumes too much gas to fit in a block. - */ - function values(AddressSet storage set) internal view returns (address[] memory) { - bytes32[] memory store = _values(set._inner); - address[] memory result; - - /// @solidity memory-safe-assembly - assembly { - result := store - } - - return result; - } - - // UintSet - - struct UintSet { - Set _inner; - } - - /** - * @dev Add a value to a set. O(1). - * - * Returns true if the value was added to the set, that is if it was not - * already present. - */ - function add(UintSet storage set, uint256 value) internal returns (bool) { - return _add(set._inner, bytes32(value)); - } - - /** - * @dev Removes a value from a set. O(1). - * - * Returns true if the value was removed from the set, that is if it was - * present. - */ - function remove(UintSet storage set, uint256 value) internal returns (bool) { - return _remove(set._inner, bytes32(value)); - } - - /** - * @dev Returns true if the value is in the set. O(1). - */ - function contains(UintSet storage set, uint256 value) internal view returns (bool) { - return _contains(set._inner, bytes32(value)); - } - - /** - * @dev Returns the number of values on the set. O(1). - */ - function length(UintSet storage set) internal view returns (uint256) { - return _length(set._inner); - } - - /** - * @dev Returns the value stored at position `index` in the set. O(1). - * - * Note that there are no guarantees on the ordering of values inside the - * array, and it may change when more values are added or removed. - * - * Requirements: - * - * - `index` must be strictly less than {length}. - */ - function at(UintSet storage set, uint256 index) internal view returns (uint256) { - return uint256(_at(set._inner, index)); - } - - /** - * @dev Return the entire set in an array - * - * WARNING: This operation will copy the entire storage to memory, which can be quite expensive. This is designed - * to mostly be used by view accessors that are queried without any gas fees. Developers should keep in mind that - * this function has an unbounded cost, and using it as part of a state-changing function may render the function - * uncallable if the set grows to a point where copying to memory consumes too much gas to fit in a block. - */ - function values(UintSet storage set) internal view returns (uint256[] memory) { - bytes32[] memory store = _values(set._inner); - uint256[] memory result; - - /// @solidity memory-safe-assembly - assembly { - result := store - } - - return result; - } -} - - -contract ActivityPool is Operator { - using SafeMath for uint256; - using SafeERC20 for IERC20; - using EnumerableSet for EnumerableSet.AddressSet; - using EnumerableSet for EnumerableSet.UintSet; - - event AddNewAct(uint256 id); - event Bet(address user, uint256 pID, uint256 bType, uint256 amount, uint256 time); - event SetPrize(uint256 pID, uint256 bType); - event Claim(address user, uint256 pID, uint256 bType, uint256 amount); - event RemovePeriodAct(uint256 pID); - - uint256 public constant muti = 1e18; - uint256 public periodID; - uint256 public betID; - - struct UserInfo { - address user; - uint256 pID; - uint256 amount; - uint256 betTime; - uint256 bType; - uint256 claimAmount; - } - - struct ActInfo { - string name; - string aName; - string bName; - address rewardToken; - uint256 startTime; - uint256 endTime; - uint256 minAmount; - uint256 maxAmount; - uint256 aAmount; - uint256 bAmount; - uint256 winType; - bool isBet; - } - - struct TimeInfo { - uint256 time; - uint256 aAmount; - uint256 bAmount; - } - - struct BestInfo { - address aUser; - address bUser; - uint256 aBet; - uint256 bBet; - } - - mapping(uint256 => BestInfo) bestInfo; - mapping(uint256 => uint256) public timeID; - mapping(uint256 => mapping(uint256 => TimeInfo)) public timeInfo; - mapping(address => mapping(uint256 => uint256)) public userBet; - mapping(uint256 => UserInfo) public betInfo; - mapping(uint256 => uint256) public perAmount; - mapping(uint256 => ActInfo) public actInfo; - mapping(uint256 => mapping(uint256 => string)) public descripName; - - mapping(address => EnumerableSet.UintSet) userPid; - mapping(uint256 => EnumerableSet.AddressSet) aUsers; - mapping(uint256 => EnumerableSet.AddressSet) bUsers; - EnumerableSet.UintSet activePeriod; - EnumerableSet.UintSet removePeriod; - - function addNewAct( - string memory name, - string memory aName, - string memory bName, - address token, - uint256 startTime, - uint256 endTime, - uint256 minAmount, - uint256 maxAmount - ) external onlyOperator { - - checkAdd(msg.sender, startTime, endTime, minAmount, maxAmount); - uint256 id = ++periodID; - actInfo[id].name = name; - actInfo[id].aName = aName; - actInfo[id].bName = bName; - actInfo[id].startTime = startTime; - actInfo[id].endTime = endTime; - actInfo[id].minAmount = minAmount; - actInfo[id].maxAmount = maxAmount; - actInfo[id].rewardToken = token; - descripName[id][1] = aName; - descripName[id][2] = bName; - activePeriod.add(id); - - emit AddNewAct(id); - } - - - function removePeriodAct(uint256 pID) external onlyOperator { - checkRemove(pID); - - activePeriod.remove(pID); - removePeriod.add(pID); - - emit RemovePeriodAct(pID); - } - - - function bet(uint256 pID, uint256 bType, uint256 amount) external payable { - checkBet(msg.sender, pID, bType, amount); - if(actInfo[pID].rewardToken == address(0)) { - require(msg.value == amount, "value err"); - } else { - require(msg.value == 0, "value amount err"); - } - - if(bType == 1) { - if(amount > bestInfo[pID].aBet) { - bestInfo[pID].aUser = msg.sender; - bestInfo[pID].aBet = amount; - } - } else { - if(amount > bestInfo[pID].bBet) { - bestInfo[pID].bUser = msg.sender; - bestInfo[pID].bBet = amount; - } - } - - userPid[msg.sender].add(pID); - uint256 id = ++betID; - userBet[msg.sender][pID] = id; - - if(bType == 1) { - aUsers[pID].add(msg.sender); - actInfo[pID].aAmount = actInfo[pID].aAmount.add(amount); - } else { - bUsers[pID].add(msg.sender); - actInfo[pID].bAmount = actInfo[pID].bAmount.add(amount); - } - - actInfo[pID].isBet = true; - betInfo[id].user = msg.sender; - betInfo[id].pID = pID; - betInfo[id].amount = amount; - betInfo[id].betTime = block.timestamp; - betInfo[id].bType = bType; - - uint256 tID = ++timeID[pID]; - timeInfo[pID][tID].time = block.timestamp; - timeInfo[pID][tID].aAmount = actInfo[pID].aAmount; - timeInfo[pID][tID].bAmount = actInfo[pID].bAmount; - - if(actInfo[pID].rewardToken != address(0)) { - IERC20(actInfo[pID].rewardToken).safeTransferFrom(msg.sender, address(this), amount); - } - emit Bet(msg.sender, pID, bType, amount, betInfo[id].betTime); - } - - function setPrize(uint256 pID, uint256 bType) external onlyOperator { - checkSetPrize(msg.sender, pID, bType); - - if(block.timestamp <= actInfo[pID].startTime) { - actInfo[pID].startTime = block.timestamp; - - } - actInfo[pID].endTime = block.timestamp; - - actInfo[pID].winType = bType; - perAmount[pID] = getPerAmount(pID, bType); - - emit SetPrize(pID, bType); - } - - function recive() public payable {} - - function claim(uint256 pID) external { - uint256 amount = checkClaim(msg.sender, pID); - - uint256 id = userBet[msg.sender][pID]; - betInfo[id].claimAmount = amount; - if(actInfo[pID].rewardToken != address(0)) { - IERC20(actInfo[pID].rewardToken).safeTransfer(msg.sender, amount); - } else { - payable(msg.sender).transfer(amount); - } - - emit Claim(msg.sender, pID, betInfo[id].bType, amount); - } - - function checkClaim(address user, uint256 pID) public view returns(uint256 amount) { - require(userPid[user].contains(pID), "not bet"); - uint256 id = userBet[user][pID]; - require(betInfo[id].user == user, "not user"); - require(actInfo[pID].winType != 0, "not prize"); - require(betInfo[id].claimAmount == 0, "has claim"); - - if(actInfo[pID].winType != 3) { - require(actInfo[pID].winType == betInfo[id].bType, "not right"); - amount = perAmount[pID].mul(betInfo[id].amount).div(muti); - require(amount > 0, "no amount"); - } else { - amount = betInfo[id].amount; - } - - return amount; - } - - function getActualRate( - address user, - uint256 pID, - uint256 bType, - uint256 amount - ) external view returns(uint256, uint256, bool) { - if(bType < 1 || bType > 2 || !activePeriod.contains(pID)) { - return (0, 0, false); - } else if(userBet[user][pID] != 0 || actInfo[pID].winType != 0 || amount == 0) { - (uint256 ra, uint256 rb) = getRate(pID, timeID[pID]); - return (ra, rb, false); - } else { - (uint256 aAmount, uint256 bAmount) = (actInfo[pID].aAmount, actInfo[pID].bAmount); - if(bType == 1) { - aAmount = aAmount.add(amount); - } else { - bAmount = bAmount.add(amount); - } - - uint256 total = aAmount.add(bAmount); - if(bAmount == 0 && aAmount != 0) { - return (muti, 0, true); - } - if(bAmount != 0 && aAmount == 0) { - return (0, muti, true); - } - return (total.mul(muti).div(aAmount), total.mul(muti).div(bAmount), true); - } - } - - function getRate(uint256 pID, uint256 tID) public view returns(uint256, uint256) { - (uint256 aAmount, uint256 bAmount) = (timeInfo[pID][tID].aAmount, timeInfo[pID][tID].bAmount); - uint256 total = aAmount.add(bAmount); - if(total == 0) { - return (0, 0); - } - if(bAmount == 0 && aAmount != 0) { - return (muti, 0); - } - if(bAmount != 0 && aAmount == 0) { - return (0, muti); - } - return (total.mul(muti).div(aAmount), total.mul(muti).div(bAmount)); - } - - function getBestInfo(uint256 pID) - external - view - returns(address aUser, address bUser, uint256 aBet, uint256 bBet, uint256 aReward, uint256 bReward) - { - aUser = bestInfo[pID].aUser; - bUser = bestInfo[pID].bUser; - aBet = bestInfo[pID].aBet; - bBet = bestInfo[pID].bBet; - aReward = getPerAmount(pID, 1).mul(aBet).div(muti); - bReward = getPerAmount(pID, 2).mul(bBet).div(muti); - } - - function getPerAmount(uint256 pID, uint256 bType) public view returns(uint256) { - uint256 total = actInfo[pID].aAmount.add(actInfo[pID].bAmount); - if(total == 0) { - return 0; - } - - if(actInfo[pID].winType == 3) { - return muti; - } - - if(bType == 1) { - if(actInfo[pID].aAmount == 0 || actInfo[pID].winType == 2) { - return 0; - } - return total.mul(muti).div(actInfo[pID].aAmount); - } - - if(bType == 2) { - if(actInfo[pID].bAmount == 0 || actInfo[pID].winType == 1) { - return 0; - } - return total.mul(muti).div(actInfo[pID].bAmount); - } - - return 0; - - } - - function checkSetPrize(address user, uint256 pID, uint256 bType) public view returns(bool) { - require(user == owner() || user == operator, "no permission"); - require(bType > 0 && bType <= 3, "type err"); - require(activePeriod.contains(pID), "not active"); - require(actInfo[pID].winType == 0, "has set"); - - return true; - } - - function checkBet( - address user, - uint256 pID, - uint256 bType, - uint256 amount - ) public view returns(bool) { - require(activePeriod.contains(pID), "not active"); - require(actInfo[pID].startTime <= block.timestamp, "not start"); - require(actInfo[pID].endTime > block.timestamp, "has end"); - require(!userPid[user].contains(pID), "has bet"); - require(bType > 0 && bType < 3, "type err"); - require(amount >= actInfo[pID].minAmount && amount <= actInfo[pID].maxAmount, "amount err"); - if(actInfo[pID].rewardToken != address(0)) { - require(IERC20(actInfo[pID].rewardToken).allowance(user, address(this)) >= amount, "not approve enough"); - require(IERC20(actInfo[pID].rewardToken).balanceOf(user) >= amount, "not enough"); - } else { - require(user.balance >= amount, "main token err"); - } - - return true; - } - - - function checkRemove(uint256 pID) public view returns(bool) { - require(activePeriod.contains(pID), "not in"); - require(!actInfo[pID].isBet, "has bet"); - - return true; - } - - function checkAdd( - address user, - uint256 startTime, - uint256 endTime, - uint256 minAmount, - uint256 maxAmount - ) public view returns(bool) { - require(user == owner() || user == operator, "no permission"); - require(startTime > block.timestamp, "startTime err"); - require(endTime > startTime, "endTime err"); - require(minAmount > 0 && maxAmount > minAmount, "amount err"); - - return true; - } - - function getStatus(uint256 pID) external view returns(uint256) { - if(!removePeriod.contains(pID) && !activePeriod.contains(pID)) { - return 5; - } else if(removePeriod.contains(pID)) { - return 6; - } else if(block.timestamp < actInfo[pID].startTime) { - return 1; - } else if ( - actInfo[pID].startTime <= block.timestamp && - actInfo[pID].endTime > block.timestamp - ) { - return 2; - } else if (actInfo[pID].endTime <= block.timestamp && actInfo[pID].winType == 0){ - return 3; - } else if(actInfo[pID].winType != 0) { - return 4; - } - return 0; - } - - function getUserPidNum(address user) external view returns(uint256) { - return userPid[user].length(); - } - - function getUserPid(address user, uint256 index) external view returns(uint256) { - return userPid[user].at(index); - } - - function getAUsersNum(uint256 pID) external view returns(uint256) { - return aUsers[pID].length(); - } - - function getAUsers(uint256 pID, uint256 index) external view returns(address) { - return aUsers[pID].at(index); - } - - function getBUsersNum(uint256 pID) external view returns(uint256) { - return bUsers[pID].length(); - } - - function getBUsers(uint256 pID, uint256 index) external view returns(address) { - return bUsers[pID].at(index); - } - - function getActivePeriodNum() external view returns(uint256) { - return activePeriod.length(); - } - - function getActivePeriod(uint256 index) external view returns(uint256) { - return activePeriod.at(index); - } - - function getRemovePeriodNum() external view returns(uint256) { - return removePeriod.length(); - } - - function getRemovePeriod(uint256 index) external view returns(uint256) { - return removePeriod.at(index); - } -} \ No newline at end of file diff --git a/app/api/uploads/ActivityPool-1729808603511-614676959.sol b/app/api/uploads/ActivityPool-1729808603511-614676959.sol deleted file mode 100644 index daf3372..0000000 --- a/app/api/uploads/ActivityPool-1729808603511-614676959.sol +++ /dev/null @@ -1,1648 +0,0 @@ -// SPDX-License-Identifier: MIT -// OpenZeppelin Contracts (last updated v4.7.0) (utils/Address.sol) - -pragma solidity ^0.8.1; - -/** - * @dev Collection of functions related to the address type - */ -library Address { - /** - * @dev Returns true if `account` is a contract. - * - * [IMPORTANT] - * ==== - * It is unsafe to assume that an address for which this function returns - * false is an externally-owned account (EOA) and not a contract. - * - * Among others, `isContract` will return false for the following - * types of addresses: - * - * - an externally-owned account - * - a contract in construction - * - an address where a contract will be created - * - an address where a contract lived, but was destroyed - * ==== - * - * [IMPORTANT] - * ==== - * You shouldn't rely on `isContract` to protect against flash loan attacks! - * - * Preventing calls from contracts is highly discouraged. It breaks composability, breaks support for smart wallets - * like Gnosis Safe, and does not provide security since it can be circumvented by calling from a contract - * constructor. - * ==== - */ - function isContract(address account) internal view returns (bool) { - // This method relies on extcodesize/address.code.length, which returns 0 - // for contracts in construction, since the code is only stored at the end - // of the constructor execution. - - return account.code.length > 0; - } - - /** - * @dev Replacement for Solidity's `transfer`: sends `amount` wei to - * `recipient`, forwarding all available gas and reverting on errors. - * - * https://eips.ethereum.org/EIPS/eip-1884[EIP1884] increases the gas cost - * of certain opcodes, possibly making contracts go over the 2300 gas limit - * imposed by `transfer`, making them unable to receive funds via - * `transfer`. {sendValue} removes this limitation. - * - * https://diligence.consensys.net/posts/2019/09/stop-using-soliditys-transfer-now/[Learn more]. - * - * IMPORTANT: because control is transferred to `recipient`, care must be - * taken to not create reentrancy vulnerabilities. Consider using - * {ReentrancyGuard} or the - * https://solidity.readthedocs.io/en/v0.5.11/security-considerations.html#use-the-checks-effects-interactions-pattern[checks-effects-interactions pattern]. - */ - function sendValue(address payable recipient, uint256 amount) internal { - require(address(this).balance >= amount, "Address: insufficient balance"); - - (bool success, ) = recipient.call{value: amount}(""); - require(success, "Address: unable to send value, recipient may have reverted"); - } - - /** - * @dev Performs a Solidity function call using a low level `call`. A - * plain `call` is an unsafe replacement for a function call: use this - * function instead. - * - * If `target` reverts with a revert reason, it is bubbled up by this - * function (like regular Solidity function calls). - * - * Returns the raw returned data. To convert to the expected return value, - * use https://solidity.readthedocs.io/en/latest/units-and-global-variables.html?highlight=abi.decode#abi-encoding-and-decoding-functions[`abi.decode`]. - * - * Requirements: - * - * - `target` must be a contract. - * - calling `target` with `data` must not revert. - * - * _Available since v3.1._ - */ - function functionCall(address target, bytes memory data) internal returns (bytes memory) { - return functionCallWithValue(target, data, 0, "Address: low-level call failed"); - } - - /** - * @dev Same as {xref-Address-functionCall-address-bytes-}[`functionCall`], but with - * `errorMessage` as a fallback revert reason when `target` reverts. - * - * _Available since v3.1._ - */ - function functionCall( - address target, - bytes memory data, - string memory errorMessage - ) internal returns (bytes memory) { - return functionCallWithValue(target, data, 0, errorMessage); - } - - /** - * @dev Same as {xref-Address-functionCall-address-bytes-}[`functionCall`], - * but also transferring `value` wei to `target`. - * - * Requirements: - * - * - the calling contract must have an ETH balance of at least `value`. - * - the called Solidity function must be `payable`. - * - * _Available since v3.1._ - */ - function functionCallWithValue( - address target, - bytes memory data, - uint256 value - ) internal returns (bytes memory) { - return functionCallWithValue(target, data, value, "Address: low-level call with value failed"); - } - - /** - * @dev Same as {xref-Address-functionCallWithValue-address-bytes-uint256-}[`functionCallWithValue`], but - * with `errorMessage` as a fallback revert reason when `target` reverts. - * - * _Available since v3.1._ - */ - function functionCallWithValue( - address target, - bytes memory data, - uint256 value, - string memory errorMessage - ) internal returns (bytes memory) { - require(address(this).balance >= value, "Address: insufficient balance for call"); - (bool success, bytes memory returndata) = target.call{value: value}(data); - return verifyCallResultFromTarget(target, success, returndata, errorMessage); - } - - /** - * @dev Same as {xref-Address-functionCall-address-bytes-}[`functionCall`], - * but performing a static call. - * - * _Available since v3.3._ - */ - function functionStaticCall(address target, bytes memory data) internal view returns (bytes memory) { - return functionStaticCall(target, data, "Address: low-level static call failed"); - } - - /** - * @dev Same as {xref-Address-functionCall-address-bytes-string-}[`functionCall`], - * but performing a static call. - * - * _Available since v3.3._ - */ - function functionStaticCall( - address target, - bytes memory data, - string memory errorMessage - ) internal view returns (bytes memory) { - (bool success, bytes memory returndata) = target.staticcall(data); - return verifyCallResultFromTarget(target, success, returndata, errorMessage); - } - - /** - * @dev Same as {xref-Address-functionCall-address-bytes-}[`functionCall`], - * but performing a delegate call. - * - * _Available since v3.4._ - */ - function functionDelegateCall(address target, bytes memory data) internal returns (bytes memory) { - return functionDelegateCall(target, data, "Address: low-level delegate call failed"); - } - - /** - * @dev Same as {xref-Address-functionCall-address-bytes-string-}[`functionCall`], - * but performing a delegate call. - * - * _Available since v3.4._ - */ - function functionDelegateCall( - address target, - bytes memory data, - string memory errorMessage - ) internal returns (bytes memory) { - (bool success, bytes memory returndata) = target.delegatecall(data); - return verifyCallResultFromTarget(target, success, returndata, errorMessage); - } - - /** - * @dev Tool to verify that a low level call to smart-contract was successful, and revert (either by bubbling - * the revert reason or using the provided one) in case of unsuccessful call or if target was not a contract. - * - * _Available since v4.8._ - */ - function verifyCallResultFromTarget( - address target, - bool success, - bytes memory returndata, - string memory errorMessage - ) internal view returns (bytes memory) { - if (success) { - if (returndata.length == 0) { - // only check isContract if the call was successful and the return data is empty - // otherwise we already know that it was a contract - require(isContract(target), "Address: call to non-contract"); - } - return returndata; - } else { - _revert(returndata, errorMessage); - } - } - - /** - * @dev Tool to verify that a low level call was successful, and revert if it wasn't, either by bubbling the - * revert reason or using the provided one. - * - * _Available since v4.3._ - */ - function verifyCallResult( - bool success, - bytes memory returndata, - string memory errorMessage - ) internal pure returns (bytes memory) { - if (success) { - return returndata; - } else { - _revert(returndata, errorMessage); - } - } - - function _revert(bytes memory returndata, string memory errorMessage) private pure { - // Look for revert reason and bubble it up if present - if (returndata.length > 0) { - // The easiest way to bubble the revert reason is using memory via assembly - /// @solidity memory-safe-assembly - assembly { - let returndata_size := mload(returndata) - revert(add(32, returndata), returndata_size) - } - } else { - revert(errorMessage); - } - } -} - -// OpenZeppelin Contracts (last updated v4.6.0) (token/ERC20/IERC20.sol) - - - -/** - * @dev Interface of the ERC20 standard as defined in the EIP. - */ -interface IERC20 { - /** - * @dev Emitted when `value` tokens are moved from one account (`from`) to - * another (`to`). - * - * Note that `value` may be zero. - */ - event Transfer(address indexed from, address indexed to, uint256 value); - - /** - * @dev Emitted when the allowance of a `spender` for an `owner` is set by - * a call to {approve}. `value` is the new allowance. - */ - event Approval(address indexed owner, address indexed spender, uint256 value); - - /** - * @dev Returns the amount of tokens in existence. - */ - function totalSupply() external view returns (uint256); - - /** - * @dev Returns the amount of tokens owned by `account`. - */ - function balanceOf(address account) external view returns (uint256); - - /** - * @dev Moves `amount` tokens from the caller's account to `to`. - * - * Returns a boolean value indicating whether the operation succeeded. - * - * Emits a {Transfer} event. - */ - function transfer(address to, uint256 amount) external returns (bool); - - /** - * @dev Returns the remaining number of tokens that `spender` will be - * allowed to spend on behalf of `owner` through {transferFrom}. This is - * zero by default. - * - * This value changes when {approve} or {transferFrom} are called. - */ - function allowance(address owner, address spender) external view returns (uint256); - - /** - * @dev Sets `amount` as the allowance of `spender` over the caller's tokens. - * - * Returns a boolean value indicating whether the operation succeeded. - * - * IMPORTANT: Beware that changing an allowance with this method brings the risk - * that someone may use both the old and the new allowance by unfortunate - * transaction ordering. One possible solution to mitigate this race - * condition is to first reduce the spender's allowance to 0 and set the - * desired value afterwards: - * https://github.com/ethereum/EIPs/issues/20#issuecomment-263524729 - * - * Emits an {Approval} event. - */ - function approve(address spender, uint256 amount) external returns (bool); - - /** - * @dev Moves `amount` tokens from `from` to `to` using the - * allowance mechanism. `amount` is then deducted from the caller's - * allowance. - * - * Returns a boolean value indicating whether the operation succeeded. - * - * Emits a {Transfer} event. - */ - function transferFrom( - address from, - address to, - uint256 amount - ) external returns (bool); - - - function mint(address account_, uint256 amount_) external; - - function burn(uint256 amount) external; - -} - - - - - - - - - - - -/** - * @dev Wrappers over Solidity's arithmetic operations with added overflow - * checks. - * - * Arithmetic operations in Solidity wrap on overflow. This can easily result - * in bugs, because programmers usually assume that an overflow raises an - * error, which is the standard behavior in high level programming languages. - * `SafeMath` restores this intuition by reverting the transaction when an - * operation overflows. - * - * Using this library instead of the unchecked operations eliminates an entire - * class of bugs, so it's recommended to use it always. - */ -library SafeMath { - /** - * @dev Returns the addition of two unsigned integers, reverting on - * overflow. - * - * Counterpart to Solidity's `+` operator. - * - * Requirements: - * - * - Addition cannot overflow. - */ - function add(uint256 a, uint256 b) internal pure returns (uint256) { - uint256 c = a + b; - require(c >= a, "SafeMath: addition overflow"); - - return c; - } - - /** - * @dev Returns the subtraction of two unsigned integers, reverting on - * overflow (when the result is negative). - * - * Counterpart to Solidity's `-` operator. - * - * Requirements: - * - * - Subtraction cannot overflow. - */ - function sub(uint256 a, uint256 b) internal pure returns (uint256) { - return sub(a, b, "SafeMath: subtraction overflow"); - } - - /** - * @dev Returns the subtraction of two unsigned integers, reverting with custom message on - * overflow (when the result is negative). - * - * Counterpart to Solidity's `-` operator. - * - * Requirements: - * - * - Subtraction cannot overflow. - */ - function sub( - uint256 a, - uint256 b, - string memory errorMessage - ) internal pure returns (uint256) { - require(b <= a, errorMessage); - uint256 c = a - b; - - return c; - } - - /** - * @dev Returns the multiplication of two unsigned integers, reverting on - * overflow. - * - * Counterpart to Solidity's `*` operator. - * - * Requirements: - * - * - Multiplication cannot overflow. - */ - function mul(uint256 a, uint256 b) internal pure returns (uint256) { - // Gas optimization: this is cheaper than requiring 'a' not being zero, but the - // benefit is lost if 'b' is also tested. - // See: https://github.com/OpenZeppelin/openzeppelin-contracts/pull/522 - if (a == 0) { - return 0; - } - - uint256 c = a * b; - require(c / a == b, "SafeMath: multiplication overflow"); - - return c; - } - - /** - * @dev Returns the integer division of two unsigned integers. Reverts on - * division by zero. The result is rounded towards zero. - * - * Counterpart to Solidity's `/` operator. Note: this function uses a - * `revert` opcode (which leaves remaining gas untouched) while Solidity - * uses an invalid opcode to revert (consuming all remaining gas). - * - * Requirements: - * - * - The divisor cannot be zero. - */ - function div(uint256 a, uint256 b) internal pure returns (uint256) { - return div(a, b, "SafeMath: division by zero"); - } - - /** - * @dev Returns the integer division of two unsigned integers. Reverts with custom message on - * division by zero. The result is rounded towards zero. - * - * Counterpart to Solidity's `/` operator. Note: this function uses a - * `revert` opcode (which leaves remaining gas untouched) while Solidity - * uses an invalid opcode to revert (consuming all remaining gas). - * - * Requirements: - * - * - The divisor cannot be zero. - */ - function div( - uint256 a, - uint256 b, - string memory errorMessage - ) internal pure returns (uint256) { - require(b > 0, errorMessage); - uint256 c = a / b; - // assert(a == b * c + a % b); // There is no case in which this doesn't hold - - return c; - } - - /** - * @dev Returns the remainder of dividing two unsigned integers. (unsigned integer modulo), - * Reverts when dividing by zero. - * - * Counterpart to Solidity's `%` operator. This function uses a `revert` - * opcode (which leaves remaining gas untouched) while Solidity uses an - * invalid opcode to revert (consuming all remaining gas). - * - * Requirements: - * - * - The divisor cannot be zero. - */ - function mod(uint256 a, uint256 b) internal pure returns (uint256) { - return mod(a, b, "SafeMath: modulo by zero"); - } - - /** - * @dev Returns the remainder of dividing two unsigned integers. (unsigned integer modulo), - * Reverts with custom message when dividing by zero. - * - * Counterpart to Solidity's `%` operator. This function uses a `revert` - * opcode (which leaves remaining gas untouched) while Solidity uses an - * invalid opcode to revert (consuming all remaining gas). - * - * Requirements: - * - * - The divisor cannot be zero. - */ - function mod( - uint256 a, - uint256 b, - string memory errorMessage - ) internal pure returns (uint256) { - require(b != 0, errorMessage); - return a % b; - } - - // babylonian method (https://en.wikipedia.org/wiki/Methods_of_computing_square_roots#Babylonian_method) - function sqrrt(uint256 a) internal pure returns (uint256 c) { - if (a > 3) { - c = a; - uint256 b = add(div(a, 2), 1); - while (b < c) { - c = b; - b = div(add(div(a, b), b), 2); - } - } else if (a != 0) { - c = 1; - } - } - - /* - * Expects percentage to be trailed by 00, - */ - function percentageAmount(uint256 total_, uint8 percentage_) internal pure returns (uint256 percentAmount_) { - return div(mul(total_, percentage_), 1000); - } - - /* - * Expects percentage to be trailed by 00, - */ - function substractPercentage(uint256 total_, uint8 percentageToSub_) internal pure returns (uint256 result_) { - return sub(total_, div(mul(total_, percentageToSub_), 1000)); - } - - function percentageOfTotal(uint256 part_, uint256 total_) internal pure returns (uint256 percent_) { - return div(mul(part_, 100), total_); - } - - /** - * Taken from Hypersonic https://github.com/M2629/HyperSonic/blob/main/Math.sol - * @dev Returns the average of two numbers. The result is rounded towards - * zero. - */ - function average(uint256 a, uint256 b) internal pure returns (uint256) { - // (a + b) / 2 can overflow, so we distribute - return (a / 2) + (b / 2) + (((a % 2) + (b % 2)) / 2); - } - - function quadraticPricing(uint256 payment_, uint256 multiplier_) internal pure returns (uint256) { - return sqrrt(mul(multiplier_, payment_)); - } - - function bondingCurve(uint256 supply_, uint256 multiplier_) internal pure returns (uint256) { - return mul(multiplier_, supply_); - } -} - -// OpenZeppelin Contracts (last updated v4.7.0) (token/ERC20/utils/SafeERC20.sol) - - - - - -// OpenZeppelin Contracts v4.4.1 (token/ERC20/extensions/draft-IERC20Permit.sol) - - - -/** - * @dev Interface of the ERC20 Permit extension allowing approvals to be made via signatures, as defined in - * https://eips.ethereum.org/EIPS/eip-2612[EIP-2612]. - * - * Adds the {permit} method, which can be used to change an account's ERC20 allowance (see {IERC20-allowance}) by - * presenting a message signed by the account. By not relying on {IERC20-approve}, the token holder account doesn't - * need to send a transaction, and thus is not required to hold Ether at all. - */ -interface IERC20Permit { - /** - * @dev Sets `value` as the allowance of `spender` over ``owner``'s tokens, - * given ``owner``'s signed approval. - * - * IMPORTANT: The same issues {IERC20-approve} has related to transaction - * ordering also apply here. - * - * Emits an {Approval} event. - * - * Requirements: - * - * - `spender` cannot be the zero address. - * - `deadline` must be a timestamp in the future. - * - `v`, `r` and `s` must be a valid `secp256k1` signature from `owner` - * over the EIP712-formatted function arguments. - * - the signature must use ``owner``'s current nonce (see {nonces}). - * - * For more information on the signature format, see the - * https://eips.ethereum.org/EIPS/eip-2612#specification[relevant EIP - * section]. - */ - function permit( - address owner, - address spender, - uint256 value, - uint256 deadline, - uint8 v, - bytes32 r, - bytes32 s - ) external; - - /** - * @dev Returns the current nonce for `owner`. This value must be - * included whenever a signature is generated for {permit}. - * - * Every successful call to {permit} increases ``owner``'s nonce by one. This - * prevents a signature from being used multiple times. - */ - function nonces(address owner) external view returns (uint256); - - /** - * @dev Returns the domain separator used in the encoding of the signature for {permit}, as defined by {EIP712}. - */ - // solhint-disable-next-line func-name-mixedcase - function DOMAIN_SEPARATOR() external view returns (bytes32); -} - - - -/** - * @title SafeERC20 - * @dev Wrappers around ERC20 operations that throw on failure (when the token - * contract returns false). Tokens that return no value (and instead revert or - * throw on failure) are also supported, non-reverting calls are assumed to be - * successful. - * To use this library you can add a `using SafeERC20 for IERC20;` statement to your contract, - * which allows you to call the safe operations as `token.safeTransfer(...)`, etc. - */ -library SafeERC20 { - using Address for address; - - function safeTransfer( - IERC20 token, - address to, - uint256 value - ) internal { - _callOptionalReturn(token, abi.encodeWithSelector(token.transfer.selector, to, value)); - } - - function safeTransferFrom( - IERC20 token, - address from, - address to, - uint256 value - ) internal { - _callOptionalReturn(token, abi.encodeWithSelector(token.transferFrom.selector, from, to, value)); - } - - /** - * @dev Deprecated. This function has issues similar to the ones found in - * {IERC20-approve}, and its usage is discouraged. - * - * Whenever possible, use {safeIncreaseAllowance} and - * {safeDecreaseAllowance} instead. - */ - function safeApprove( - IERC20 token, - address spender, - uint256 value - ) internal { - // safeApprove should only be called when setting an initial allowance, - // or when resetting it to zero. To increase and decrease it, use - // 'safeIncreaseAllowance' and 'safeDecreaseAllowance' - require( - (value == 0) || (token.allowance(address(this), spender) == 0), - "SafeERC20: approve from non-zero to non-zero allowance" - ); - _callOptionalReturn(token, abi.encodeWithSelector(token.approve.selector, spender, value)); - } - - function safeIncreaseAllowance( - IERC20 token, - address spender, - uint256 value - ) internal { - uint256 newAllowance = token.allowance(address(this), spender) + value; - _callOptionalReturn(token, abi.encodeWithSelector(token.approve.selector, spender, newAllowance)); - } - - function safeDecreaseAllowance( - IERC20 token, - address spender, - uint256 value - ) internal { - unchecked { - uint256 oldAllowance = token.allowance(address(this), spender); - require(oldAllowance >= value, "SafeERC20: decreased allowance below zero"); - uint256 newAllowance = oldAllowance - value; - _callOptionalReturn(token, abi.encodeWithSelector(token.approve.selector, spender, newAllowance)); - } - } - - function safePermit( - IERC20Permit token, - address owner, - address spender, - uint256 value, - uint256 deadline, - uint8 v, - bytes32 r, - bytes32 s - ) internal { - uint256 nonceBefore = token.nonces(owner); - token.permit(owner, spender, value, deadline, v, r, s); - uint256 nonceAfter = token.nonces(owner); - require(nonceAfter == nonceBefore + 1, "SafeERC20: permit did not succeed"); - } - - /** - * @dev Imitates a Solidity high-level call (i.e. a regular function call to a contract), relaxing the requirement - * on the return value: the return value is optional (but if data is returned, it must not be false). - * @param token The token targeted by the call. - * @param data The call data (encoded using abi.encode or one of its variants). - */ - function _callOptionalReturn(IERC20 token, bytes memory data) private { - // We need to perform a low level call here, to bypass Solidity's return data size checking mechanism, since - // we're implementing it ourselves. We use {Address.functionCall} to perform this call, which verifies that - // the target address contains contract code and also asserts for success in the low-level call. - - bytes memory returndata = address(token).functionCall(data, "SafeERC20: low-level call failed"); - if (returndata.length > 0) { - // Return data is optional - require(abi.decode(returndata, (bool)), "SafeERC20: ERC20 operation did not succeed"); - } - } -} - - - - - - - - - - - - - - -/** - * @dev Provides information about the current execution context, including the - * sender of the transaction and its data. While these are generally available - * via msg.sender and msg.data, they should not be accessed in such a direct - * manner, since when dealing with meta-transactions the account sending and - * paying for execution may not be the actual sender (as far as an application - * is concerned). - * - * This contract is only required for intermediate, library-like contracts. - */ -abstract contract Context { - function _msgSender() internal view virtual returns (address) { - return msg.sender; - } - - function _msgData() internal view virtual returns (bytes calldata) { - return msg.data; - } -} - - -/** - * @dev Contract module which provides a basic access control mechanism, where - * there is an account (an owner) that can be granted exclusive access to - * specific functions. - * - * By default, the owner account will be the one that deploys the contract. This - * can later be changed with {transferOwnership}. - * - * This module is used through inheritance. It will make available the modifier - * `onlyOwner`, which can be applied to your functions to restrict their use to - * the owner. - */ -abstract contract Ownable is Context { - address private _owner; - - event OwnershipTransferred(address indexed previousOwner, address indexed newOwner); - - /** - * @dev Initializes the contract setting the deployer as the initial owner. - */ - constructor() { - _transferOwnership(_msgSender()); - } - - /** - * @dev Throws if called by any account other than the owner. - */ - modifier onlyOwner() { - _checkOwner(); - _; - } - - /** - * @dev Returns the address of the current owner. - */ - function owner() public view virtual returns (address) { - return _owner; - } - - /** - * @dev Throws if the sender is not the owner. - */ - function _checkOwner() internal view virtual { - require(owner() == _msgSender(), "Ownable: caller is not the owner"); - } - - /** - * @dev Leaves the contract without owner. It will not be possible to call - * `onlyOwner` functions anymore. Can only be called by the current owner. - * - * NOTE: Renouncing ownership will leave the contract without an owner, - * thereby removing any functionality that is only available to the owner. - */ - function renounceOwnership() public virtual onlyOwner { - _transferOwnership(address(0)); - } - - /** - * @dev Transfers ownership of the contract to a new account (`newOwner`). - * Can only be called by the current owner. - */ - function transferOwnership(address newOwner) public virtual onlyOwner { - require(newOwner != address(0), "Ownable: new owner is the zero address"); - _transferOwnership(newOwner); - } - - /** - * @dev Transfers ownership of the contract to a new account (`newOwner`). - * Internal function without access restriction. - */ - function _transferOwnership(address newOwner) internal virtual { - address oldOwner = _owner; - _owner = newOwner; - emit OwnershipTransferred(oldOwner, newOwner); - } -} - - -contract Operator is Ownable { - address public operator; - uint256 constant baseRate = 10000; - - modifier onlyOperator { - require(msg.sender == owner() || msg.sender == operator, "no permission"); - _; - } - - function setOperator(address operator_) external onlyOwner { - operator = operator_; - } - - - function getCurrTime() external view returns(uint256) { - return block.timestamp; - } - - function getBlockNum() external view returns(uint256) { - return block.number; - } - -} - - - - - -/** - * @dev Library for managing - * https://en.wikipedia.org/wiki/Set_(abstract_data_type)[sets] of primitive - * types. - * - * Sets have the following properties: - * - * - Elements are added, removed, and checked for existence in constant time - * (O(1)). - * - Elements are enumerated in O(n). No guarantees are made on the ordering. - * - * ``` - * contract Example { - * // Add the library methods - * using EnumerableSet for EnumerableSet.AddressSet; - * - * // Declare a set state variable - * EnumerableSet.AddressSet private mySet; - * } - * ``` - * - * As of v3.3.0, sets of type `bytes32` (`Bytes32Set`), `address` (`AddressSet`) - * and `uint256` (`UintSet`) are supported. - * - * [WARNING] - * ==== - * Trying to delete such a structure from storage will likely result in data corruption, rendering the structure unusable. - * See https://github.com/ethereum/solidity/pull/11843[ethereum/solidity#11843] for more info. - * - * In order to clean an EnumerableSet, you can either remove all elements one by one or create a fresh instance using an array of EnumerableSet. - * ==== - */ - -library EnumerableSet { - // To implement this library for multiple types with as little code - // repetition as possible, we write it in terms of a generic Set type with - // bytes32 values. - // The Set implementation uses private functions, and user-facing - // implementations (such as AddressSet) are just wrappers around the - // underlying Set. - // This means that we can only create new EnumerableSets for types that fit - // in bytes32. - - struct Set { - // Storage of set values - bytes32[] _values; - // Position of the value in the `values` array, plus 1 because index 0 - // means a value is not in the set. - mapping(bytes32 => uint256) _indexes; - } - - /** - * @dev Add a value to a set. O(1). - * - * Returns true if the value was added to the set, that is if it was not - * already present. - */ - function _add(Set storage set, bytes32 value) private returns (bool) { - if (!_contains(set, value)) { - set._values.push(value); - // The value is stored at length-1, but we add 1 to all indexes - // and use 0 as a sentinel value - set._indexes[value] = set._values.length; - return true; - } else { - return false; - } - } - - /** - * @dev Removes a value from a set. O(1). - * - * Returns true if the value was removed from the set, that is if it was - * present. - */ - function _remove(Set storage set, bytes32 value) private returns (bool) { - // We read and store the value's index to prevent multiple reads from the same storage slot - uint256 valueIndex = set._indexes[value]; - - if (valueIndex != 0) { - // Equivalent to contains(set, value) - // To delete an element from the _values array in O(1), we swap the element to delete with the last one in - // the array, and then remove the last element (sometimes called as 'swap and pop'). - // This modifies the order of the array, as noted in {at}. - - uint256 toDeleteIndex = valueIndex - 1; - uint256 lastIndex = set._values.length - 1; - - if (lastIndex != toDeleteIndex) { - bytes32 lastValue = set._values[lastIndex]; - - // Move the last value to the index where the value to delete is - set._values[toDeleteIndex] = lastValue; - // Update the index for the moved value - set._indexes[lastValue] = valueIndex; // Replace lastValue's index to valueIndex - } - - // Delete the slot where the moved value was stored - set._values.pop(); - - // Delete the index for the deleted slot - delete set._indexes[value]; - - return true; - } else { - return false; - } - } - - /** - * @dev Returns true if the value is in the set. O(1). - */ - function _contains(Set storage set, bytes32 value) private view returns (bool) { - return set._indexes[value] != 0; - } - - /** - * @dev Returns the number of values on the set. O(1). - */ - function _length(Set storage set) private view returns (uint256) { - return set._values.length; - } - - /** - * @dev Returns the value stored at position `index` in the set. O(1). - * - * Note that there are no guarantees on the ordering of values inside the - * array, and it may change when more values are added or removed. - * - * Requirements: - * - * - `index` must be strictly less than {length}. - */ - function _at(Set storage set, uint256 index) private view returns (bytes32) { - return set._values[index]; - } - - /** - * @dev Return the entire set in an array - * - * WARNING: This operation will copy the entire storage to memory, which can be quite expensive. This is designed - * to mostly be used by view accessors that are queried without any gas fees. Developers should keep in mind that - * this function has an unbounded cost, and using it as part of a state-changing function may render the function - * uncallable if the set grows to a point where copying to memory consumes too much gas to fit in a block. - */ - function _values(Set storage set) private view returns (bytes32[] memory) { - return set._values; - } - - // Bytes32Set - - struct Bytes32Set { - Set _inner; - } - - /** - * @dev Add a value to a set. O(1). - * - * Returns true if the value was added to the set, that is if it was not - * already present. - */ - function add(Bytes32Set storage set, bytes32 value) internal returns (bool) { - return _add(set._inner, value); - } - - /** - * @dev Removes a value from a set. O(1). - * - * Returns true if the value was removed from the set, that is if it was - * present. - */ - function remove(Bytes32Set storage set, bytes32 value) internal returns (bool) { - return _remove(set._inner, value); - } - - /** - * @dev Returns true if the value is in the set. O(1). - */ - function contains(Bytes32Set storage set, bytes32 value) internal view returns (bool) { - return _contains(set._inner, value); - } - - /** - * @dev Returns the number of values in the set. O(1). - */ - function length(Bytes32Set storage set) internal view returns (uint256) { - return _length(set._inner); - } - - /** - * @dev Returns the value stored at position `index` in the set. O(1). - * - * Note that there are no guarantees on the ordering of values inside the - * array, and it may change when more values are added or removed. - * - * Requirements: - * - * - `index` must be strictly less than {length}. - */ - function at(Bytes32Set storage set, uint256 index) internal view returns (bytes32) { - return _at(set._inner, index); - } - - /** - * @dev Return the entire set in an array - * - * WARNING: This operation will copy the entire storage to memory, which can be quite expensive. This is designed - * to mostly be used by view accessors that are queried without any gas fees. Developers should keep in mind that - * this function has an unbounded cost, and using it as part of a state-changing function may render the function - * uncallable if the set grows to a point where copying to memory consumes too much gas to fit in a block. - */ - function values(Bytes32Set storage set) internal view returns (bytes32[] memory) { - return _values(set._inner); - } - - // AddressSet - - struct AddressSet { - Set _inner; - } - - /** - * @dev Add a value to a set. O(1). - * - * Returns true if the value was added to the set, that is if it was not - * already present. - */ - function add(AddressSet storage set, address value) internal returns (bool) { - return _add(set._inner, bytes32(uint256(uint160(value)))); - } - - /** - * @dev Removes a value from a set. O(1). - * - * Returns true if the value was removed from the set, that is if it was - * present. - */ - function remove(AddressSet storage set, address value) internal returns (bool) { - return _remove(set._inner, bytes32(uint256(uint160(value)))); - } - - /** - * @dev Returns true if the value is in the set. O(1). - */ - function contains(AddressSet storage set, address value) internal view returns (bool) { - return _contains(set._inner, bytes32(uint256(uint160(value)))); - } - - /** - * @dev Returns the number of values in the set. O(1). - */ - function length(AddressSet storage set) internal view returns (uint256) { - return _length(set._inner); - } - - /** - * @dev Returns the value stored at position `index` in the set. O(1). - * - * Note that there are no guarantees on the ordering of values inside the - * array, and it may change when more values are added or removed. - * - * Requirements: - * - * - `index` must be strictly less than {length}. - */ - function at(AddressSet storage set, uint256 index) internal view returns (address) { - return address(uint160(uint256(_at(set._inner, index)))); - } - - /** - * @dev Return the entire set in an array - * - * WARNING: This operation will copy the entire storage to memory, which can be quite expensive. This is designed - * to mostly be used by view accessors that are queried without any gas fees. Developers should keep in mind that - * this function has an unbounded cost, and using it as part of a state-changing function may render the function - * uncallable if the set grows to a point where copying to memory consumes too much gas to fit in a block. - */ - function values(AddressSet storage set) internal view returns (address[] memory) { - bytes32[] memory store = _values(set._inner); - address[] memory result; - - /// @solidity memory-safe-assembly - assembly { - result := store - } - - return result; - } - - // UintSet - - struct UintSet { - Set _inner; - } - - /** - * @dev Add a value to a set. O(1). - * - * Returns true if the value was added to the set, that is if it was not - * already present. - */ - function add(UintSet storage set, uint256 value) internal returns (bool) { - return _add(set._inner, bytes32(value)); - } - - /** - * @dev Removes a value from a set. O(1). - * - * Returns true if the value was removed from the set, that is if it was - * present. - */ - function remove(UintSet storage set, uint256 value) internal returns (bool) { - return _remove(set._inner, bytes32(value)); - } - - /** - * @dev Returns true if the value is in the set. O(1). - */ - function contains(UintSet storage set, uint256 value) internal view returns (bool) { - return _contains(set._inner, bytes32(value)); - } - - /** - * @dev Returns the number of values on the set. O(1). - */ - function length(UintSet storage set) internal view returns (uint256) { - return _length(set._inner); - } - - /** - * @dev Returns the value stored at position `index` in the set. O(1). - * - * Note that there are no guarantees on the ordering of values inside the - * array, and it may change when more values are added or removed. - * - * Requirements: - * - * - `index` must be strictly less than {length}. - */ - function at(UintSet storage set, uint256 index) internal view returns (uint256) { - return uint256(_at(set._inner, index)); - } - - /** - * @dev Return the entire set in an array - * - * WARNING: This operation will copy the entire storage to memory, which can be quite expensive. This is designed - * to mostly be used by view accessors that are queried without any gas fees. Developers should keep in mind that - * this function has an unbounded cost, and using it as part of a state-changing function may render the function - * uncallable if the set grows to a point where copying to memory consumes too much gas to fit in a block. - */ - function values(UintSet storage set) internal view returns (uint256[] memory) { - bytes32[] memory store = _values(set._inner); - uint256[] memory result; - - /// @solidity memory-safe-assembly - assembly { - result := store - } - - return result; - } -} - - -contract ActivityPool is Operator { - using SafeMath for uint256; - using SafeERC20 for IERC20; - using EnumerableSet for EnumerableSet.AddressSet; - using EnumerableSet for EnumerableSet.UintSet; - - event AddNewAct(uint256 id); - event Bet(address user, uint256 pID, uint256 bType, uint256 amount, uint256 time); - event SetPrize(uint256 pID, uint256 bType); - event Claim(address user, uint256 pID, uint256 bType, uint256 amount); - event RemovePeriodAct(uint256 pID); - - uint256 public constant muti = 1e18; - uint256 public periodID; - uint256 public betID; - - struct UserInfo { - address user; - uint256 pID; - uint256 amount; - uint256 betTime; - uint256 bType; - uint256 claimAmount; - } - - struct ActInfo { - string name; - string aName; - string bName; - address rewardToken; - uint256 startTime; - uint256 endTime; - uint256 minAmount; - uint256 maxAmount; - uint256 aAmount; - uint256 bAmount; - uint256 winType; - bool isBet; - } - - struct TimeInfo { - uint256 time; - uint256 aAmount; - uint256 bAmount; - } - - struct BestInfo { - address aUser; - address bUser; - uint256 aBet; - uint256 bBet; - } - - mapping(uint256 => BestInfo) bestInfo; - mapping(uint256 => uint256) public timeID; - mapping(uint256 => mapping(uint256 => TimeInfo)) public timeInfo; - mapping(address => mapping(uint256 => uint256)) public userBet; - mapping(uint256 => UserInfo) public betInfo; - mapping(uint256 => uint256) public perAmount; - mapping(uint256 => ActInfo) public actInfo; - mapping(uint256 => mapping(uint256 => string)) public descripName; - - mapping(address => EnumerableSet.UintSet) userPid; - mapping(uint256 => EnumerableSet.AddressSet) aUsers; - mapping(uint256 => EnumerableSet.AddressSet) bUsers; - EnumerableSet.UintSet activePeriod; - EnumerableSet.UintSet removePeriod; - - function addNewAct( - string memory name, - string memory aName, - string memory bName, - address token, - uint256 startTime, - uint256 endTime, - uint256 minAmount, - uint256 maxAmount - ) external onlyOperator { - - checkAdd(msg.sender, startTime, endTime, minAmount, maxAmount); - uint256 id = ++periodID; - actInfo[id].name = name; - actInfo[id].aName = aName; - actInfo[id].bName = bName; - actInfo[id].startTime = startTime; - actInfo[id].endTime = endTime; - actInfo[id].minAmount = minAmount; - actInfo[id].maxAmount = maxAmount; - actInfo[id].rewardToken = token; - descripName[id][1] = aName; - descripName[id][2] = bName; - activePeriod.add(id); - - emit AddNewAct(id); - } - - - function removePeriodAct(uint256 pID) external onlyOperator { - checkRemove(pID); - - activePeriod.remove(pID); - removePeriod.add(pID); - - emit RemovePeriodAct(pID); - } - - - function bet(uint256 pID, uint256 bType, uint256 amount) external payable { - checkBet(msg.sender, pID, bType, amount); - if(actInfo[pID].rewardToken == address(0)) { - require(msg.value == amount, "value err"); - } else { - require(msg.value == 0, "value amount err"); - } - - if(bType == 1) { - if(amount > bestInfo[pID].aBet) { - bestInfo[pID].aUser = msg.sender; - bestInfo[pID].aBet = amount; - } - } else { - if(amount > bestInfo[pID].bBet) { - bestInfo[pID].bUser = msg.sender; - bestInfo[pID].bBet = amount; - } - } - - userPid[msg.sender].add(pID); - uint256 id = ++betID; - userBet[msg.sender][pID] = id; - - if(bType == 1) { - aUsers[pID].add(msg.sender); - actInfo[pID].aAmount = actInfo[pID].aAmount.add(amount); - } else { - bUsers[pID].add(msg.sender); - actInfo[pID].bAmount = actInfo[pID].bAmount.add(amount); - } - - actInfo[pID].isBet = true; - betInfo[id].user = msg.sender; - betInfo[id].pID = pID; - betInfo[id].amount = amount; - betInfo[id].betTime = block.timestamp; - betInfo[id].bType = bType; - - uint256 tID = ++timeID[pID]; - timeInfo[pID][tID].time = block.timestamp; - timeInfo[pID][tID].aAmount = actInfo[pID].aAmount; - timeInfo[pID][tID].bAmount = actInfo[pID].bAmount; - - if(actInfo[pID].rewardToken != address(0)) { - IERC20(actInfo[pID].rewardToken).safeTransferFrom(msg.sender, address(this), amount); - } - emit Bet(msg.sender, pID, bType, amount, betInfo[id].betTime); - } - - function setPrize(uint256 pID, uint256 bType) external onlyOperator { - checkSetPrize(msg.sender, pID, bType); - - if(block.timestamp <= actInfo[pID].startTime) { - actInfo[pID].startTime = block.timestamp; - - } - actInfo[pID].endTime = block.timestamp; - - actInfo[pID].winType = bType; - perAmount[pID] = getPerAmount(pID, bType); - - emit SetPrize(pID, bType); - } - - function recive() public payable {} - - function claim(uint256 pID) external { - uint256 amount = checkClaim(msg.sender, pID); - - uint256 id = userBet[msg.sender][pID]; - betInfo[id].claimAmount = amount; - if(actInfo[pID].rewardToken != address(0)) { - IERC20(actInfo[pID].rewardToken).safeTransfer(msg.sender, amount); - } else { - payable(msg.sender).transfer(amount); - } - - emit Claim(msg.sender, pID, betInfo[id].bType, amount); - } - - function checkClaim(address user, uint256 pID) public view returns(uint256 amount) { - require(userPid[user].contains(pID), "not bet"); - uint256 id = userBet[user][pID]; - require(betInfo[id].user == user, "not user"); - require(actInfo[pID].winType != 0, "not prize"); - require(betInfo[id].claimAmount == 0, "has claim"); - - if(actInfo[pID].winType != 3) { - require(actInfo[pID].winType == betInfo[id].bType, "not right"); - amount = perAmount[pID].mul(betInfo[id].amount).div(muti); - require(amount > 0, "no amount"); - } else { - amount = betInfo[id].amount; - } - - return amount; - } - - function getActualRate( - address user, - uint256 pID, - uint256 bType, - uint256 amount - ) external view returns(uint256, uint256, bool) { - if(bType < 1 || bType > 2 || !activePeriod.contains(pID)) { - return (0, 0, false); - } else if(userBet[user][pID] != 0 || actInfo[pID].winType != 0 || amount == 0) { - (uint256 ra, uint256 rb) = getRate(pID, timeID[pID]); - return (ra, rb, false); - } else { - (uint256 aAmount, uint256 bAmount) = (actInfo[pID].aAmount, actInfo[pID].bAmount); - if(bType == 1) { - aAmount = aAmount.add(amount); - } else { - bAmount = bAmount.add(amount); - } - - uint256 total = aAmount.add(bAmount); - if(bAmount == 0 && aAmount != 0) { - return (muti, 0, true); - } - if(bAmount != 0 && aAmount == 0) { - return (0, muti, true); - } - return (total.mul(muti).div(aAmount), total.mul(muti).div(bAmount), true); - } - } - - function getRate(uint256 pID, uint256 tID) public view returns(uint256, uint256) { - (uint256 aAmount, uint256 bAmount) = (timeInfo[pID][tID].aAmount, timeInfo[pID][tID].bAmount); - uint256 total = aAmount.add(bAmount); - if(total == 0) { - return (0, 0); - } - if(bAmount == 0 && aAmount != 0) { - return (muti, 0); - } - if(bAmount != 0 && aAmount == 0) { - return (0, muti); - } - return (total.mul(muti).div(aAmount), total.mul(muti).div(bAmount)); - } - - function getBestInfo(uint256 pID) - external - view - returns(address aUser, address bUser, uint256 aBet, uint256 bBet, uint256 aReward, uint256 bReward) - { - aUser = bestInfo[pID].aUser; - bUser = bestInfo[pID].bUser; - aBet = bestInfo[pID].aBet; - bBet = bestInfo[pID].bBet; - aReward = getPerAmount(pID, 1).mul(aBet).div(muti); - bReward = getPerAmount(pID, 2).mul(bBet).div(muti); - } - - function getPerAmount(uint256 pID, uint256 bType) public view returns(uint256) { - uint256 total = actInfo[pID].aAmount.add(actInfo[pID].bAmount); - if(total == 0) { - return 0; - } - - if(actInfo[pID].winType == 3) { - return muti; - } - - if(bType == 1) { - if(actInfo[pID].aAmount == 0 || actInfo[pID].winType == 2) { - return 0; - } - return total.mul(muti).div(actInfo[pID].aAmount); - } - - if(bType == 2) { - if(actInfo[pID].bAmount == 0 || actInfo[pID].winType == 1) { - return 0; - } - return total.mul(muti).div(actInfo[pID].bAmount); - } - - return 0; - - } - - function checkSetPrize(address user, uint256 pID, uint256 bType) public view returns(bool) { - require(user == owner() || user == operator, "no permission"); - require(bType > 0 && bType <= 3, "type err"); - require(activePeriod.contains(pID), "not active"); - require(actInfo[pID].winType == 0, "has set"); - - return true; - } - - function checkBet( - address user, - uint256 pID, - uint256 bType, - uint256 amount - ) public view returns(bool) { - require(activePeriod.contains(pID), "not active"); - require(actInfo[pID].startTime <= block.timestamp, "not start"); - require(actInfo[pID].endTime > block.timestamp, "has end"); - require(!userPid[user].contains(pID), "has bet"); - require(bType > 0 && bType < 3, "type err"); - require(amount >= actInfo[pID].minAmount && amount <= actInfo[pID].maxAmount, "amount err"); - if(actInfo[pID].rewardToken != address(0)) { - require(IERC20(actInfo[pID].rewardToken).allowance(user, address(this)) >= amount, "not approve enough"); - require(IERC20(actInfo[pID].rewardToken).balanceOf(user) >= amount, "not enough"); - } else { - require(user.balance >= amount, "main token err"); - } - - return true; - } - - - function checkRemove(uint256 pID) public view returns(bool) { - require(activePeriod.contains(pID), "not in"); - require(!actInfo[pID].isBet, "has bet"); - - return true; - } - - function checkAdd( - address user, - uint256 startTime, - uint256 endTime, - uint256 minAmount, - uint256 maxAmount - ) public view returns(bool) { - require(user == owner() || user == operator, "no permission"); - require(startTime > block.timestamp, "startTime err"); - require(endTime > startTime, "endTime err"); - require(minAmount > 0 && maxAmount > minAmount, "amount err"); - - return true; - } - - function getStatus(uint256 pID) external view returns(uint256) { - if(!removePeriod.contains(pID) && !activePeriod.contains(pID)) { - return 5; - } else if(removePeriod.contains(pID)) { - return 6; - } else if(block.timestamp < actInfo[pID].startTime) { - return 1; - } else if ( - actInfo[pID].startTime <= block.timestamp && - actInfo[pID].endTime > block.timestamp - ) { - return 2; - } else if (actInfo[pID].endTime <= block.timestamp && actInfo[pID].winType == 0){ - return 3; - } else if(actInfo[pID].winType != 0) { - return 4; - } - return 0; - } - - function getUserPidNum(address user) external view returns(uint256) { - return userPid[user].length(); - } - - function getUserPid(address user, uint256 index) external view returns(uint256) { - return userPid[user].at(index); - } - - function getAUsersNum(uint256 pID) external view returns(uint256) { - return aUsers[pID].length(); - } - - function getAUsers(uint256 pID, uint256 index) external view returns(address) { - return aUsers[pID].at(index); - } - - function getBUsersNum(uint256 pID) external view returns(uint256) { - return bUsers[pID].length(); - } - - function getBUsers(uint256 pID, uint256 index) external view returns(address) { - return bUsers[pID].at(index); - } - - function getActivePeriodNum() external view returns(uint256) { - return activePeriod.length(); - } - - function getActivePeriod(uint256 index) external view returns(uint256) { - return activePeriod.at(index); - } - - function getRemovePeriodNum() external view returns(uint256) { - return removePeriod.length(); - } - - function getRemovePeriod(uint256 index) external view returns(uint256) { - return removePeriod.at(index); - } -} \ No newline at end of file diff --git a/app/api/uploads/ActivityPool-1729820423782-940160024.sol b/app/api/uploads/ActivityPool-1729820423782-940160024.sol deleted file mode 100644 index daf3372..0000000 --- a/app/api/uploads/ActivityPool-1729820423782-940160024.sol +++ /dev/null @@ -1,1648 +0,0 @@ -// SPDX-License-Identifier: MIT -// OpenZeppelin Contracts (last updated v4.7.0) (utils/Address.sol) - -pragma solidity ^0.8.1; - -/** - * @dev Collection of functions related to the address type - */ -library Address { - /** - * @dev Returns true if `account` is a contract. - * - * [IMPORTANT] - * ==== - * It is unsafe to assume that an address for which this function returns - * false is an externally-owned account (EOA) and not a contract. - * - * Among others, `isContract` will return false for the following - * types of addresses: - * - * - an externally-owned account - * - a contract in construction - * - an address where a contract will be created - * - an address where a contract lived, but was destroyed - * ==== - * - * [IMPORTANT] - * ==== - * You shouldn't rely on `isContract` to protect against flash loan attacks! - * - * Preventing calls from contracts is highly discouraged. It breaks composability, breaks support for smart wallets - * like Gnosis Safe, and does not provide security since it can be circumvented by calling from a contract - * constructor. - * ==== - */ - function isContract(address account) internal view returns (bool) { - // This method relies on extcodesize/address.code.length, which returns 0 - // for contracts in construction, since the code is only stored at the end - // of the constructor execution. - - return account.code.length > 0; - } - - /** - * @dev Replacement for Solidity's `transfer`: sends `amount` wei to - * `recipient`, forwarding all available gas and reverting on errors. - * - * https://eips.ethereum.org/EIPS/eip-1884[EIP1884] increases the gas cost - * of certain opcodes, possibly making contracts go over the 2300 gas limit - * imposed by `transfer`, making them unable to receive funds via - * `transfer`. {sendValue} removes this limitation. - * - * https://diligence.consensys.net/posts/2019/09/stop-using-soliditys-transfer-now/[Learn more]. - * - * IMPORTANT: because control is transferred to `recipient`, care must be - * taken to not create reentrancy vulnerabilities. Consider using - * {ReentrancyGuard} or the - * https://solidity.readthedocs.io/en/v0.5.11/security-considerations.html#use-the-checks-effects-interactions-pattern[checks-effects-interactions pattern]. - */ - function sendValue(address payable recipient, uint256 amount) internal { - require(address(this).balance >= amount, "Address: insufficient balance"); - - (bool success, ) = recipient.call{value: amount}(""); - require(success, "Address: unable to send value, recipient may have reverted"); - } - - /** - * @dev Performs a Solidity function call using a low level `call`. A - * plain `call` is an unsafe replacement for a function call: use this - * function instead. - * - * If `target` reverts with a revert reason, it is bubbled up by this - * function (like regular Solidity function calls). - * - * Returns the raw returned data. To convert to the expected return value, - * use https://solidity.readthedocs.io/en/latest/units-and-global-variables.html?highlight=abi.decode#abi-encoding-and-decoding-functions[`abi.decode`]. - * - * Requirements: - * - * - `target` must be a contract. - * - calling `target` with `data` must not revert. - * - * _Available since v3.1._ - */ - function functionCall(address target, bytes memory data) internal returns (bytes memory) { - return functionCallWithValue(target, data, 0, "Address: low-level call failed"); - } - - /** - * @dev Same as {xref-Address-functionCall-address-bytes-}[`functionCall`], but with - * `errorMessage` as a fallback revert reason when `target` reverts. - * - * _Available since v3.1._ - */ - function functionCall( - address target, - bytes memory data, - string memory errorMessage - ) internal returns (bytes memory) { - return functionCallWithValue(target, data, 0, errorMessage); - } - - /** - * @dev Same as {xref-Address-functionCall-address-bytes-}[`functionCall`], - * but also transferring `value` wei to `target`. - * - * Requirements: - * - * - the calling contract must have an ETH balance of at least `value`. - * - the called Solidity function must be `payable`. - * - * _Available since v3.1._ - */ - function functionCallWithValue( - address target, - bytes memory data, - uint256 value - ) internal returns (bytes memory) { - return functionCallWithValue(target, data, value, "Address: low-level call with value failed"); - } - - /** - * @dev Same as {xref-Address-functionCallWithValue-address-bytes-uint256-}[`functionCallWithValue`], but - * with `errorMessage` as a fallback revert reason when `target` reverts. - * - * _Available since v3.1._ - */ - function functionCallWithValue( - address target, - bytes memory data, - uint256 value, - string memory errorMessage - ) internal returns (bytes memory) { - require(address(this).balance >= value, "Address: insufficient balance for call"); - (bool success, bytes memory returndata) = target.call{value: value}(data); - return verifyCallResultFromTarget(target, success, returndata, errorMessage); - } - - /** - * @dev Same as {xref-Address-functionCall-address-bytes-}[`functionCall`], - * but performing a static call. - * - * _Available since v3.3._ - */ - function functionStaticCall(address target, bytes memory data) internal view returns (bytes memory) { - return functionStaticCall(target, data, "Address: low-level static call failed"); - } - - /** - * @dev Same as {xref-Address-functionCall-address-bytes-string-}[`functionCall`], - * but performing a static call. - * - * _Available since v3.3._ - */ - function functionStaticCall( - address target, - bytes memory data, - string memory errorMessage - ) internal view returns (bytes memory) { - (bool success, bytes memory returndata) = target.staticcall(data); - return verifyCallResultFromTarget(target, success, returndata, errorMessage); - } - - /** - * @dev Same as {xref-Address-functionCall-address-bytes-}[`functionCall`], - * but performing a delegate call. - * - * _Available since v3.4._ - */ - function functionDelegateCall(address target, bytes memory data) internal returns (bytes memory) { - return functionDelegateCall(target, data, "Address: low-level delegate call failed"); - } - - /** - * @dev Same as {xref-Address-functionCall-address-bytes-string-}[`functionCall`], - * but performing a delegate call. - * - * _Available since v3.4._ - */ - function functionDelegateCall( - address target, - bytes memory data, - string memory errorMessage - ) internal returns (bytes memory) { - (bool success, bytes memory returndata) = target.delegatecall(data); - return verifyCallResultFromTarget(target, success, returndata, errorMessage); - } - - /** - * @dev Tool to verify that a low level call to smart-contract was successful, and revert (either by bubbling - * the revert reason or using the provided one) in case of unsuccessful call or if target was not a contract. - * - * _Available since v4.8._ - */ - function verifyCallResultFromTarget( - address target, - bool success, - bytes memory returndata, - string memory errorMessage - ) internal view returns (bytes memory) { - if (success) { - if (returndata.length == 0) { - // only check isContract if the call was successful and the return data is empty - // otherwise we already know that it was a contract - require(isContract(target), "Address: call to non-contract"); - } - return returndata; - } else { - _revert(returndata, errorMessage); - } - } - - /** - * @dev Tool to verify that a low level call was successful, and revert if it wasn't, either by bubbling the - * revert reason or using the provided one. - * - * _Available since v4.3._ - */ - function verifyCallResult( - bool success, - bytes memory returndata, - string memory errorMessage - ) internal pure returns (bytes memory) { - if (success) { - return returndata; - } else { - _revert(returndata, errorMessage); - } - } - - function _revert(bytes memory returndata, string memory errorMessage) private pure { - // Look for revert reason and bubble it up if present - if (returndata.length > 0) { - // The easiest way to bubble the revert reason is using memory via assembly - /// @solidity memory-safe-assembly - assembly { - let returndata_size := mload(returndata) - revert(add(32, returndata), returndata_size) - } - } else { - revert(errorMessage); - } - } -} - -// OpenZeppelin Contracts (last updated v4.6.0) (token/ERC20/IERC20.sol) - - - -/** - * @dev Interface of the ERC20 standard as defined in the EIP. - */ -interface IERC20 { - /** - * @dev Emitted when `value` tokens are moved from one account (`from`) to - * another (`to`). - * - * Note that `value` may be zero. - */ - event Transfer(address indexed from, address indexed to, uint256 value); - - /** - * @dev Emitted when the allowance of a `spender` for an `owner` is set by - * a call to {approve}. `value` is the new allowance. - */ - event Approval(address indexed owner, address indexed spender, uint256 value); - - /** - * @dev Returns the amount of tokens in existence. - */ - function totalSupply() external view returns (uint256); - - /** - * @dev Returns the amount of tokens owned by `account`. - */ - function balanceOf(address account) external view returns (uint256); - - /** - * @dev Moves `amount` tokens from the caller's account to `to`. - * - * Returns a boolean value indicating whether the operation succeeded. - * - * Emits a {Transfer} event. - */ - function transfer(address to, uint256 amount) external returns (bool); - - /** - * @dev Returns the remaining number of tokens that `spender` will be - * allowed to spend on behalf of `owner` through {transferFrom}. This is - * zero by default. - * - * This value changes when {approve} or {transferFrom} are called. - */ - function allowance(address owner, address spender) external view returns (uint256); - - /** - * @dev Sets `amount` as the allowance of `spender` over the caller's tokens. - * - * Returns a boolean value indicating whether the operation succeeded. - * - * IMPORTANT: Beware that changing an allowance with this method brings the risk - * that someone may use both the old and the new allowance by unfortunate - * transaction ordering. One possible solution to mitigate this race - * condition is to first reduce the spender's allowance to 0 and set the - * desired value afterwards: - * https://github.com/ethereum/EIPs/issues/20#issuecomment-263524729 - * - * Emits an {Approval} event. - */ - function approve(address spender, uint256 amount) external returns (bool); - - /** - * @dev Moves `amount` tokens from `from` to `to` using the - * allowance mechanism. `amount` is then deducted from the caller's - * allowance. - * - * Returns a boolean value indicating whether the operation succeeded. - * - * Emits a {Transfer} event. - */ - function transferFrom( - address from, - address to, - uint256 amount - ) external returns (bool); - - - function mint(address account_, uint256 amount_) external; - - function burn(uint256 amount) external; - -} - - - - - - - - - - - -/** - * @dev Wrappers over Solidity's arithmetic operations with added overflow - * checks. - * - * Arithmetic operations in Solidity wrap on overflow. This can easily result - * in bugs, because programmers usually assume that an overflow raises an - * error, which is the standard behavior in high level programming languages. - * `SafeMath` restores this intuition by reverting the transaction when an - * operation overflows. - * - * Using this library instead of the unchecked operations eliminates an entire - * class of bugs, so it's recommended to use it always. - */ -library SafeMath { - /** - * @dev Returns the addition of two unsigned integers, reverting on - * overflow. - * - * Counterpart to Solidity's `+` operator. - * - * Requirements: - * - * - Addition cannot overflow. - */ - function add(uint256 a, uint256 b) internal pure returns (uint256) { - uint256 c = a + b; - require(c >= a, "SafeMath: addition overflow"); - - return c; - } - - /** - * @dev Returns the subtraction of two unsigned integers, reverting on - * overflow (when the result is negative). - * - * Counterpart to Solidity's `-` operator. - * - * Requirements: - * - * - Subtraction cannot overflow. - */ - function sub(uint256 a, uint256 b) internal pure returns (uint256) { - return sub(a, b, "SafeMath: subtraction overflow"); - } - - /** - * @dev Returns the subtraction of two unsigned integers, reverting with custom message on - * overflow (when the result is negative). - * - * Counterpart to Solidity's `-` operator. - * - * Requirements: - * - * - Subtraction cannot overflow. - */ - function sub( - uint256 a, - uint256 b, - string memory errorMessage - ) internal pure returns (uint256) { - require(b <= a, errorMessage); - uint256 c = a - b; - - return c; - } - - /** - * @dev Returns the multiplication of two unsigned integers, reverting on - * overflow. - * - * Counterpart to Solidity's `*` operator. - * - * Requirements: - * - * - Multiplication cannot overflow. - */ - function mul(uint256 a, uint256 b) internal pure returns (uint256) { - // Gas optimization: this is cheaper than requiring 'a' not being zero, but the - // benefit is lost if 'b' is also tested. - // See: https://github.com/OpenZeppelin/openzeppelin-contracts/pull/522 - if (a == 0) { - return 0; - } - - uint256 c = a * b; - require(c / a == b, "SafeMath: multiplication overflow"); - - return c; - } - - /** - * @dev Returns the integer division of two unsigned integers. Reverts on - * division by zero. The result is rounded towards zero. - * - * Counterpart to Solidity's `/` operator. Note: this function uses a - * `revert` opcode (which leaves remaining gas untouched) while Solidity - * uses an invalid opcode to revert (consuming all remaining gas). - * - * Requirements: - * - * - The divisor cannot be zero. - */ - function div(uint256 a, uint256 b) internal pure returns (uint256) { - return div(a, b, "SafeMath: division by zero"); - } - - /** - * @dev Returns the integer division of two unsigned integers. Reverts with custom message on - * division by zero. The result is rounded towards zero. - * - * Counterpart to Solidity's `/` operator. Note: this function uses a - * `revert` opcode (which leaves remaining gas untouched) while Solidity - * uses an invalid opcode to revert (consuming all remaining gas). - * - * Requirements: - * - * - The divisor cannot be zero. - */ - function div( - uint256 a, - uint256 b, - string memory errorMessage - ) internal pure returns (uint256) { - require(b > 0, errorMessage); - uint256 c = a / b; - // assert(a == b * c + a % b); // There is no case in which this doesn't hold - - return c; - } - - /** - * @dev Returns the remainder of dividing two unsigned integers. (unsigned integer modulo), - * Reverts when dividing by zero. - * - * Counterpart to Solidity's `%` operator. This function uses a `revert` - * opcode (which leaves remaining gas untouched) while Solidity uses an - * invalid opcode to revert (consuming all remaining gas). - * - * Requirements: - * - * - The divisor cannot be zero. - */ - function mod(uint256 a, uint256 b) internal pure returns (uint256) { - return mod(a, b, "SafeMath: modulo by zero"); - } - - /** - * @dev Returns the remainder of dividing two unsigned integers. (unsigned integer modulo), - * Reverts with custom message when dividing by zero. - * - * Counterpart to Solidity's `%` operator. This function uses a `revert` - * opcode (which leaves remaining gas untouched) while Solidity uses an - * invalid opcode to revert (consuming all remaining gas). - * - * Requirements: - * - * - The divisor cannot be zero. - */ - function mod( - uint256 a, - uint256 b, - string memory errorMessage - ) internal pure returns (uint256) { - require(b != 0, errorMessage); - return a % b; - } - - // babylonian method (https://en.wikipedia.org/wiki/Methods_of_computing_square_roots#Babylonian_method) - function sqrrt(uint256 a) internal pure returns (uint256 c) { - if (a > 3) { - c = a; - uint256 b = add(div(a, 2), 1); - while (b < c) { - c = b; - b = div(add(div(a, b), b), 2); - } - } else if (a != 0) { - c = 1; - } - } - - /* - * Expects percentage to be trailed by 00, - */ - function percentageAmount(uint256 total_, uint8 percentage_) internal pure returns (uint256 percentAmount_) { - return div(mul(total_, percentage_), 1000); - } - - /* - * Expects percentage to be trailed by 00, - */ - function substractPercentage(uint256 total_, uint8 percentageToSub_) internal pure returns (uint256 result_) { - return sub(total_, div(mul(total_, percentageToSub_), 1000)); - } - - function percentageOfTotal(uint256 part_, uint256 total_) internal pure returns (uint256 percent_) { - return div(mul(part_, 100), total_); - } - - /** - * Taken from Hypersonic https://github.com/M2629/HyperSonic/blob/main/Math.sol - * @dev Returns the average of two numbers. The result is rounded towards - * zero. - */ - function average(uint256 a, uint256 b) internal pure returns (uint256) { - // (a + b) / 2 can overflow, so we distribute - return (a / 2) + (b / 2) + (((a % 2) + (b % 2)) / 2); - } - - function quadraticPricing(uint256 payment_, uint256 multiplier_) internal pure returns (uint256) { - return sqrrt(mul(multiplier_, payment_)); - } - - function bondingCurve(uint256 supply_, uint256 multiplier_) internal pure returns (uint256) { - return mul(multiplier_, supply_); - } -} - -// OpenZeppelin Contracts (last updated v4.7.0) (token/ERC20/utils/SafeERC20.sol) - - - - - -// OpenZeppelin Contracts v4.4.1 (token/ERC20/extensions/draft-IERC20Permit.sol) - - - -/** - * @dev Interface of the ERC20 Permit extension allowing approvals to be made via signatures, as defined in - * https://eips.ethereum.org/EIPS/eip-2612[EIP-2612]. - * - * Adds the {permit} method, which can be used to change an account's ERC20 allowance (see {IERC20-allowance}) by - * presenting a message signed by the account. By not relying on {IERC20-approve}, the token holder account doesn't - * need to send a transaction, and thus is not required to hold Ether at all. - */ -interface IERC20Permit { - /** - * @dev Sets `value` as the allowance of `spender` over ``owner``'s tokens, - * given ``owner``'s signed approval. - * - * IMPORTANT: The same issues {IERC20-approve} has related to transaction - * ordering also apply here. - * - * Emits an {Approval} event. - * - * Requirements: - * - * - `spender` cannot be the zero address. - * - `deadline` must be a timestamp in the future. - * - `v`, `r` and `s` must be a valid `secp256k1` signature from `owner` - * over the EIP712-formatted function arguments. - * - the signature must use ``owner``'s current nonce (see {nonces}). - * - * For more information on the signature format, see the - * https://eips.ethereum.org/EIPS/eip-2612#specification[relevant EIP - * section]. - */ - function permit( - address owner, - address spender, - uint256 value, - uint256 deadline, - uint8 v, - bytes32 r, - bytes32 s - ) external; - - /** - * @dev Returns the current nonce for `owner`. This value must be - * included whenever a signature is generated for {permit}. - * - * Every successful call to {permit} increases ``owner``'s nonce by one. This - * prevents a signature from being used multiple times. - */ - function nonces(address owner) external view returns (uint256); - - /** - * @dev Returns the domain separator used in the encoding of the signature for {permit}, as defined by {EIP712}. - */ - // solhint-disable-next-line func-name-mixedcase - function DOMAIN_SEPARATOR() external view returns (bytes32); -} - - - -/** - * @title SafeERC20 - * @dev Wrappers around ERC20 operations that throw on failure (when the token - * contract returns false). Tokens that return no value (and instead revert or - * throw on failure) are also supported, non-reverting calls are assumed to be - * successful. - * To use this library you can add a `using SafeERC20 for IERC20;` statement to your contract, - * which allows you to call the safe operations as `token.safeTransfer(...)`, etc. - */ -library SafeERC20 { - using Address for address; - - function safeTransfer( - IERC20 token, - address to, - uint256 value - ) internal { - _callOptionalReturn(token, abi.encodeWithSelector(token.transfer.selector, to, value)); - } - - function safeTransferFrom( - IERC20 token, - address from, - address to, - uint256 value - ) internal { - _callOptionalReturn(token, abi.encodeWithSelector(token.transferFrom.selector, from, to, value)); - } - - /** - * @dev Deprecated. This function has issues similar to the ones found in - * {IERC20-approve}, and its usage is discouraged. - * - * Whenever possible, use {safeIncreaseAllowance} and - * {safeDecreaseAllowance} instead. - */ - function safeApprove( - IERC20 token, - address spender, - uint256 value - ) internal { - // safeApprove should only be called when setting an initial allowance, - // or when resetting it to zero. To increase and decrease it, use - // 'safeIncreaseAllowance' and 'safeDecreaseAllowance' - require( - (value == 0) || (token.allowance(address(this), spender) == 0), - "SafeERC20: approve from non-zero to non-zero allowance" - ); - _callOptionalReturn(token, abi.encodeWithSelector(token.approve.selector, spender, value)); - } - - function safeIncreaseAllowance( - IERC20 token, - address spender, - uint256 value - ) internal { - uint256 newAllowance = token.allowance(address(this), spender) + value; - _callOptionalReturn(token, abi.encodeWithSelector(token.approve.selector, spender, newAllowance)); - } - - function safeDecreaseAllowance( - IERC20 token, - address spender, - uint256 value - ) internal { - unchecked { - uint256 oldAllowance = token.allowance(address(this), spender); - require(oldAllowance >= value, "SafeERC20: decreased allowance below zero"); - uint256 newAllowance = oldAllowance - value; - _callOptionalReturn(token, abi.encodeWithSelector(token.approve.selector, spender, newAllowance)); - } - } - - function safePermit( - IERC20Permit token, - address owner, - address spender, - uint256 value, - uint256 deadline, - uint8 v, - bytes32 r, - bytes32 s - ) internal { - uint256 nonceBefore = token.nonces(owner); - token.permit(owner, spender, value, deadline, v, r, s); - uint256 nonceAfter = token.nonces(owner); - require(nonceAfter == nonceBefore + 1, "SafeERC20: permit did not succeed"); - } - - /** - * @dev Imitates a Solidity high-level call (i.e. a regular function call to a contract), relaxing the requirement - * on the return value: the return value is optional (but if data is returned, it must not be false). - * @param token The token targeted by the call. - * @param data The call data (encoded using abi.encode or one of its variants). - */ - function _callOptionalReturn(IERC20 token, bytes memory data) private { - // We need to perform a low level call here, to bypass Solidity's return data size checking mechanism, since - // we're implementing it ourselves. We use {Address.functionCall} to perform this call, which verifies that - // the target address contains contract code and also asserts for success in the low-level call. - - bytes memory returndata = address(token).functionCall(data, "SafeERC20: low-level call failed"); - if (returndata.length > 0) { - // Return data is optional - require(abi.decode(returndata, (bool)), "SafeERC20: ERC20 operation did not succeed"); - } - } -} - - - - - - - - - - - - - - -/** - * @dev Provides information about the current execution context, including the - * sender of the transaction and its data. While these are generally available - * via msg.sender and msg.data, they should not be accessed in such a direct - * manner, since when dealing with meta-transactions the account sending and - * paying for execution may not be the actual sender (as far as an application - * is concerned). - * - * This contract is only required for intermediate, library-like contracts. - */ -abstract contract Context { - function _msgSender() internal view virtual returns (address) { - return msg.sender; - } - - function _msgData() internal view virtual returns (bytes calldata) { - return msg.data; - } -} - - -/** - * @dev Contract module which provides a basic access control mechanism, where - * there is an account (an owner) that can be granted exclusive access to - * specific functions. - * - * By default, the owner account will be the one that deploys the contract. This - * can later be changed with {transferOwnership}. - * - * This module is used through inheritance. It will make available the modifier - * `onlyOwner`, which can be applied to your functions to restrict their use to - * the owner. - */ -abstract contract Ownable is Context { - address private _owner; - - event OwnershipTransferred(address indexed previousOwner, address indexed newOwner); - - /** - * @dev Initializes the contract setting the deployer as the initial owner. - */ - constructor() { - _transferOwnership(_msgSender()); - } - - /** - * @dev Throws if called by any account other than the owner. - */ - modifier onlyOwner() { - _checkOwner(); - _; - } - - /** - * @dev Returns the address of the current owner. - */ - function owner() public view virtual returns (address) { - return _owner; - } - - /** - * @dev Throws if the sender is not the owner. - */ - function _checkOwner() internal view virtual { - require(owner() == _msgSender(), "Ownable: caller is not the owner"); - } - - /** - * @dev Leaves the contract without owner. It will not be possible to call - * `onlyOwner` functions anymore. Can only be called by the current owner. - * - * NOTE: Renouncing ownership will leave the contract without an owner, - * thereby removing any functionality that is only available to the owner. - */ - function renounceOwnership() public virtual onlyOwner { - _transferOwnership(address(0)); - } - - /** - * @dev Transfers ownership of the contract to a new account (`newOwner`). - * Can only be called by the current owner. - */ - function transferOwnership(address newOwner) public virtual onlyOwner { - require(newOwner != address(0), "Ownable: new owner is the zero address"); - _transferOwnership(newOwner); - } - - /** - * @dev Transfers ownership of the contract to a new account (`newOwner`). - * Internal function without access restriction. - */ - function _transferOwnership(address newOwner) internal virtual { - address oldOwner = _owner; - _owner = newOwner; - emit OwnershipTransferred(oldOwner, newOwner); - } -} - - -contract Operator is Ownable { - address public operator; - uint256 constant baseRate = 10000; - - modifier onlyOperator { - require(msg.sender == owner() || msg.sender == operator, "no permission"); - _; - } - - function setOperator(address operator_) external onlyOwner { - operator = operator_; - } - - - function getCurrTime() external view returns(uint256) { - return block.timestamp; - } - - function getBlockNum() external view returns(uint256) { - return block.number; - } - -} - - - - - -/** - * @dev Library for managing - * https://en.wikipedia.org/wiki/Set_(abstract_data_type)[sets] of primitive - * types. - * - * Sets have the following properties: - * - * - Elements are added, removed, and checked for existence in constant time - * (O(1)). - * - Elements are enumerated in O(n). No guarantees are made on the ordering. - * - * ``` - * contract Example { - * // Add the library methods - * using EnumerableSet for EnumerableSet.AddressSet; - * - * // Declare a set state variable - * EnumerableSet.AddressSet private mySet; - * } - * ``` - * - * As of v3.3.0, sets of type `bytes32` (`Bytes32Set`), `address` (`AddressSet`) - * and `uint256` (`UintSet`) are supported. - * - * [WARNING] - * ==== - * Trying to delete such a structure from storage will likely result in data corruption, rendering the structure unusable. - * See https://github.com/ethereum/solidity/pull/11843[ethereum/solidity#11843] for more info. - * - * In order to clean an EnumerableSet, you can either remove all elements one by one or create a fresh instance using an array of EnumerableSet. - * ==== - */ - -library EnumerableSet { - // To implement this library for multiple types with as little code - // repetition as possible, we write it in terms of a generic Set type with - // bytes32 values. - // The Set implementation uses private functions, and user-facing - // implementations (such as AddressSet) are just wrappers around the - // underlying Set. - // This means that we can only create new EnumerableSets for types that fit - // in bytes32. - - struct Set { - // Storage of set values - bytes32[] _values; - // Position of the value in the `values` array, plus 1 because index 0 - // means a value is not in the set. - mapping(bytes32 => uint256) _indexes; - } - - /** - * @dev Add a value to a set. O(1). - * - * Returns true if the value was added to the set, that is if it was not - * already present. - */ - function _add(Set storage set, bytes32 value) private returns (bool) { - if (!_contains(set, value)) { - set._values.push(value); - // The value is stored at length-1, but we add 1 to all indexes - // and use 0 as a sentinel value - set._indexes[value] = set._values.length; - return true; - } else { - return false; - } - } - - /** - * @dev Removes a value from a set. O(1). - * - * Returns true if the value was removed from the set, that is if it was - * present. - */ - function _remove(Set storage set, bytes32 value) private returns (bool) { - // We read and store the value's index to prevent multiple reads from the same storage slot - uint256 valueIndex = set._indexes[value]; - - if (valueIndex != 0) { - // Equivalent to contains(set, value) - // To delete an element from the _values array in O(1), we swap the element to delete with the last one in - // the array, and then remove the last element (sometimes called as 'swap and pop'). - // This modifies the order of the array, as noted in {at}. - - uint256 toDeleteIndex = valueIndex - 1; - uint256 lastIndex = set._values.length - 1; - - if (lastIndex != toDeleteIndex) { - bytes32 lastValue = set._values[lastIndex]; - - // Move the last value to the index where the value to delete is - set._values[toDeleteIndex] = lastValue; - // Update the index for the moved value - set._indexes[lastValue] = valueIndex; // Replace lastValue's index to valueIndex - } - - // Delete the slot where the moved value was stored - set._values.pop(); - - // Delete the index for the deleted slot - delete set._indexes[value]; - - return true; - } else { - return false; - } - } - - /** - * @dev Returns true if the value is in the set. O(1). - */ - function _contains(Set storage set, bytes32 value) private view returns (bool) { - return set._indexes[value] != 0; - } - - /** - * @dev Returns the number of values on the set. O(1). - */ - function _length(Set storage set) private view returns (uint256) { - return set._values.length; - } - - /** - * @dev Returns the value stored at position `index` in the set. O(1). - * - * Note that there are no guarantees on the ordering of values inside the - * array, and it may change when more values are added or removed. - * - * Requirements: - * - * - `index` must be strictly less than {length}. - */ - function _at(Set storage set, uint256 index) private view returns (bytes32) { - return set._values[index]; - } - - /** - * @dev Return the entire set in an array - * - * WARNING: This operation will copy the entire storage to memory, which can be quite expensive. This is designed - * to mostly be used by view accessors that are queried without any gas fees. Developers should keep in mind that - * this function has an unbounded cost, and using it as part of a state-changing function may render the function - * uncallable if the set grows to a point where copying to memory consumes too much gas to fit in a block. - */ - function _values(Set storage set) private view returns (bytes32[] memory) { - return set._values; - } - - // Bytes32Set - - struct Bytes32Set { - Set _inner; - } - - /** - * @dev Add a value to a set. O(1). - * - * Returns true if the value was added to the set, that is if it was not - * already present. - */ - function add(Bytes32Set storage set, bytes32 value) internal returns (bool) { - return _add(set._inner, value); - } - - /** - * @dev Removes a value from a set. O(1). - * - * Returns true if the value was removed from the set, that is if it was - * present. - */ - function remove(Bytes32Set storage set, bytes32 value) internal returns (bool) { - return _remove(set._inner, value); - } - - /** - * @dev Returns true if the value is in the set. O(1). - */ - function contains(Bytes32Set storage set, bytes32 value) internal view returns (bool) { - return _contains(set._inner, value); - } - - /** - * @dev Returns the number of values in the set. O(1). - */ - function length(Bytes32Set storage set) internal view returns (uint256) { - return _length(set._inner); - } - - /** - * @dev Returns the value stored at position `index` in the set. O(1). - * - * Note that there are no guarantees on the ordering of values inside the - * array, and it may change when more values are added or removed. - * - * Requirements: - * - * - `index` must be strictly less than {length}. - */ - function at(Bytes32Set storage set, uint256 index) internal view returns (bytes32) { - return _at(set._inner, index); - } - - /** - * @dev Return the entire set in an array - * - * WARNING: This operation will copy the entire storage to memory, which can be quite expensive. This is designed - * to mostly be used by view accessors that are queried without any gas fees. Developers should keep in mind that - * this function has an unbounded cost, and using it as part of a state-changing function may render the function - * uncallable if the set grows to a point where copying to memory consumes too much gas to fit in a block. - */ - function values(Bytes32Set storage set) internal view returns (bytes32[] memory) { - return _values(set._inner); - } - - // AddressSet - - struct AddressSet { - Set _inner; - } - - /** - * @dev Add a value to a set. O(1). - * - * Returns true if the value was added to the set, that is if it was not - * already present. - */ - function add(AddressSet storage set, address value) internal returns (bool) { - return _add(set._inner, bytes32(uint256(uint160(value)))); - } - - /** - * @dev Removes a value from a set. O(1). - * - * Returns true if the value was removed from the set, that is if it was - * present. - */ - function remove(AddressSet storage set, address value) internal returns (bool) { - return _remove(set._inner, bytes32(uint256(uint160(value)))); - } - - /** - * @dev Returns true if the value is in the set. O(1). - */ - function contains(AddressSet storage set, address value) internal view returns (bool) { - return _contains(set._inner, bytes32(uint256(uint160(value)))); - } - - /** - * @dev Returns the number of values in the set. O(1). - */ - function length(AddressSet storage set) internal view returns (uint256) { - return _length(set._inner); - } - - /** - * @dev Returns the value stored at position `index` in the set. O(1). - * - * Note that there are no guarantees on the ordering of values inside the - * array, and it may change when more values are added or removed. - * - * Requirements: - * - * - `index` must be strictly less than {length}. - */ - function at(AddressSet storage set, uint256 index) internal view returns (address) { - return address(uint160(uint256(_at(set._inner, index)))); - } - - /** - * @dev Return the entire set in an array - * - * WARNING: This operation will copy the entire storage to memory, which can be quite expensive. This is designed - * to mostly be used by view accessors that are queried without any gas fees. Developers should keep in mind that - * this function has an unbounded cost, and using it as part of a state-changing function may render the function - * uncallable if the set grows to a point where copying to memory consumes too much gas to fit in a block. - */ - function values(AddressSet storage set) internal view returns (address[] memory) { - bytes32[] memory store = _values(set._inner); - address[] memory result; - - /// @solidity memory-safe-assembly - assembly { - result := store - } - - return result; - } - - // UintSet - - struct UintSet { - Set _inner; - } - - /** - * @dev Add a value to a set. O(1). - * - * Returns true if the value was added to the set, that is if it was not - * already present. - */ - function add(UintSet storage set, uint256 value) internal returns (bool) { - return _add(set._inner, bytes32(value)); - } - - /** - * @dev Removes a value from a set. O(1). - * - * Returns true if the value was removed from the set, that is if it was - * present. - */ - function remove(UintSet storage set, uint256 value) internal returns (bool) { - return _remove(set._inner, bytes32(value)); - } - - /** - * @dev Returns true if the value is in the set. O(1). - */ - function contains(UintSet storage set, uint256 value) internal view returns (bool) { - return _contains(set._inner, bytes32(value)); - } - - /** - * @dev Returns the number of values on the set. O(1). - */ - function length(UintSet storage set) internal view returns (uint256) { - return _length(set._inner); - } - - /** - * @dev Returns the value stored at position `index` in the set. O(1). - * - * Note that there are no guarantees on the ordering of values inside the - * array, and it may change when more values are added or removed. - * - * Requirements: - * - * - `index` must be strictly less than {length}. - */ - function at(UintSet storage set, uint256 index) internal view returns (uint256) { - return uint256(_at(set._inner, index)); - } - - /** - * @dev Return the entire set in an array - * - * WARNING: This operation will copy the entire storage to memory, which can be quite expensive. This is designed - * to mostly be used by view accessors that are queried without any gas fees. Developers should keep in mind that - * this function has an unbounded cost, and using it as part of a state-changing function may render the function - * uncallable if the set grows to a point where copying to memory consumes too much gas to fit in a block. - */ - function values(UintSet storage set) internal view returns (uint256[] memory) { - bytes32[] memory store = _values(set._inner); - uint256[] memory result; - - /// @solidity memory-safe-assembly - assembly { - result := store - } - - return result; - } -} - - -contract ActivityPool is Operator { - using SafeMath for uint256; - using SafeERC20 for IERC20; - using EnumerableSet for EnumerableSet.AddressSet; - using EnumerableSet for EnumerableSet.UintSet; - - event AddNewAct(uint256 id); - event Bet(address user, uint256 pID, uint256 bType, uint256 amount, uint256 time); - event SetPrize(uint256 pID, uint256 bType); - event Claim(address user, uint256 pID, uint256 bType, uint256 amount); - event RemovePeriodAct(uint256 pID); - - uint256 public constant muti = 1e18; - uint256 public periodID; - uint256 public betID; - - struct UserInfo { - address user; - uint256 pID; - uint256 amount; - uint256 betTime; - uint256 bType; - uint256 claimAmount; - } - - struct ActInfo { - string name; - string aName; - string bName; - address rewardToken; - uint256 startTime; - uint256 endTime; - uint256 minAmount; - uint256 maxAmount; - uint256 aAmount; - uint256 bAmount; - uint256 winType; - bool isBet; - } - - struct TimeInfo { - uint256 time; - uint256 aAmount; - uint256 bAmount; - } - - struct BestInfo { - address aUser; - address bUser; - uint256 aBet; - uint256 bBet; - } - - mapping(uint256 => BestInfo) bestInfo; - mapping(uint256 => uint256) public timeID; - mapping(uint256 => mapping(uint256 => TimeInfo)) public timeInfo; - mapping(address => mapping(uint256 => uint256)) public userBet; - mapping(uint256 => UserInfo) public betInfo; - mapping(uint256 => uint256) public perAmount; - mapping(uint256 => ActInfo) public actInfo; - mapping(uint256 => mapping(uint256 => string)) public descripName; - - mapping(address => EnumerableSet.UintSet) userPid; - mapping(uint256 => EnumerableSet.AddressSet) aUsers; - mapping(uint256 => EnumerableSet.AddressSet) bUsers; - EnumerableSet.UintSet activePeriod; - EnumerableSet.UintSet removePeriod; - - function addNewAct( - string memory name, - string memory aName, - string memory bName, - address token, - uint256 startTime, - uint256 endTime, - uint256 minAmount, - uint256 maxAmount - ) external onlyOperator { - - checkAdd(msg.sender, startTime, endTime, minAmount, maxAmount); - uint256 id = ++periodID; - actInfo[id].name = name; - actInfo[id].aName = aName; - actInfo[id].bName = bName; - actInfo[id].startTime = startTime; - actInfo[id].endTime = endTime; - actInfo[id].minAmount = minAmount; - actInfo[id].maxAmount = maxAmount; - actInfo[id].rewardToken = token; - descripName[id][1] = aName; - descripName[id][2] = bName; - activePeriod.add(id); - - emit AddNewAct(id); - } - - - function removePeriodAct(uint256 pID) external onlyOperator { - checkRemove(pID); - - activePeriod.remove(pID); - removePeriod.add(pID); - - emit RemovePeriodAct(pID); - } - - - function bet(uint256 pID, uint256 bType, uint256 amount) external payable { - checkBet(msg.sender, pID, bType, amount); - if(actInfo[pID].rewardToken == address(0)) { - require(msg.value == amount, "value err"); - } else { - require(msg.value == 0, "value amount err"); - } - - if(bType == 1) { - if(amount > bestInfo[pID].aBet) { - bestInfo[pID].aUser = msg.sender; - bestInfo[pID].aBet = amount; - } - } else { - if(amount > bestInfo[pID].bBet) { - bestInfo[pID].bUser = msg.sender; - bestInfo[pID].bBet = amount; - } - } - - userPid[msg.sender].add(pID); - uint256 id = ++betID; - userBet[msg.sender][pID] = id; - - if(bType == 1) { - aUsers[pID].add(msg.sender); - actInfo[pID].aAmount = actInfo[pID].aAmount.add(amount); - } else { - bUsers[pID].add(msg.sender); - actInfo[pID].bAmount = actInfo[pID].bAmount.add(amount); - } - - actInfo[pID].isBet = true; - betInfo[id].user = msg.sender; - betInfo[id].pID = pID; - betInfo[id].amount = amount; - betInfo[id].betTime = block.timestamp; - betInfo[id].bType = bType; - - uint256 tID = ++timeID[pID]; - timeInfo[pID][tID].time = block.timestamp; - timeInfo[pID][tID].aAmount = actInfo[pID].aAmount; - timeInfo[pID][tID].bAmount = actInfo[pID].bAmount; - - if(actInfo[pID].rewardToken != address(0)) { - IERC20(actInfo[pID].rewardToken).safeTransferFrom(msg.sender, address(this), amount); - } - emit Bet(msg.sender, pID, bType, amount, betInfo[id].betTime); - } - - function setPrize(uint256 pID, uint256 bType) external onlyOperator { - checkSetPrize(msg.sender, pID, bType); - - if(block.timestamp <= actInfo[pID].startTime) { - actInfo[pID].startTime = block.timestamp; - - } - actInfo[pID].endTime = block.timestamp; - - actInfo[pID].winType = bType; - perAmount[pID] = getPerAmount(pID, bType); - - emit SetPrize(pID, bType); - } - - function recive() public payable {} - - function claim(uint256 pID) external { - uint256 amount = checkClaim(msg.sender, pID); - - uint256 id = userBet[msg.sender][pID]; - betInfo[id].claimAmount = amount; - if(actInfo[pID].rewardToken != address(0)) { - IERC20(actInfo[pID].rewardToken).safeTransfer(msg.sender, amount); - } else { - payable(msg.sender).transfer(amount); - } - - emit Claim(msg.sender, pID, betInfo[id].bType, amount); - } - - function checkClaim(address user, uint256 pID) public view returns(uint256 amount) { - require(userPid[user].contains(pID), "not bet"); - uint256 id = userBet[user][pID]; - require(betInfo[id].user == user, "not user"); - require(actInfo[pID].winType != 0, "not prize"); - require(betInfo[id].claimAmount == 0, "has claim"); - - if(actInfo[pID].winType != 3) { - require(actInfo[pID].winType == betInfo[id].bType, "not right"); - amount = perAmount[pID].mul(betInfo[id].amount).div(muti); - require(amount > 0, "no amount"); - } else { - amount = betInfo[id].amount; - } - - return amount; - } - - function getActualRate( - address user, - uint256 pID, - uint256 bType, - uint256 amount - ) external view returns(uint256, uint256, bool) { - if(bType < 1 || bType > 2 || !activePeriod.contains(pID)) { - return (0, 0, false); - } else if(userBet[user][pID] != 0 || actInfo[pID].winType != 0 || amount == 0) { - (uint256 ra, uint256 rb) = getRate(pID, timeID[pID]); - return (ra, rb, false); - } else { - (uint256 aAmount, uint256 bAmount) = (actInfo[pID].aAmount, actInfo[pID].bAmount); - if(bType == 1) { - aAmount = aAmount.add(amount); - } else { - bAmount = bAmount.add(amount); - } - - uint256 total = aAmount.add(bAmount); - if(bAmount == 0 && aAmount != 0) { - return (muti, 0, true); - } - if(bAmount != 0 && aAmount == 0) { - return (0, muti, true); - } - return (total.mul(muti).div(aAmount), total.mul(muti).div(bAmount), true); - } - } - - function getRate(uint256 pID, uint256 tID) public view returns(uint256, uint256) { - (uint256 aAmount, uint256 bAmount) = (timeInfo[pID][tID].aAmount, timeInfo[pID][tID].bAmount); - uint256 total = aAmount.add(bAmount); - if(total == 0) { - return (0, 0); - } - if(bAmount == 0 && aAmount != 0) { - return (muti, 0); - } - if(bAmount != 0 && aAmount == 0) { - return (0, muti); - } - return (total.mul(muti).div(aAmount), total.mul(muti).div(bAmount)); - } - - function getBestInfo(uint256 pID) - external - view - returns(address aUser, address bUser, uint256 aBet, uint256 bBet, uint256 aReward, uint256 bReward) - { - aUser = bestInfo[pID].aUser; - bUser = bestInfo[pID].bUser; - aBet = bestInfo[pID].aBet; - bBet = bestInfo[pID].bBet; - aReward = getPerAmount(pID, 1).mul(aBet).div(muti); - bReward = getPerAmount(pID, 2).mul(bBet).div(muti); - } - - function getPerAmount(uint256 pID, uint256 bType) public view returns(uint256) { - uint256 total = actInfo[pID].aAmount.add(actInfo[pID].bAmount); - if(total == 0) { - return 0; - } - - if(actInfo[pID].winType == 3) { - return muti; - } - - if(bType == 1) { - if(actInfo[pID].aAmount == 0 || actInfo[pID].winType == 2) { - return 0; - } - return total.mul(muti).div(actInfo[pID].aAmount); - } - - if(bType == 2) { - if(actInfo[pID].bAmount == 0 || actInfo[pID].winType == 1) { - return 0; - } - return total.mul(muti).div(actInfo[pID].bAmount); - } - - return 0; - - } - - function checkSetPrize(address user, uint256 pID, uint256 bType) public view returns(bool) { - require(user == owner() || user == operator, "no permission"); - require(bType > 0 && bType <= 3, "type err"); - require(activePeriod.contains(pID), "not active"); - require(actInfo[pID].winType == 0, "has set"); - - return true; - } - - function checkBet( - address user, - uint256 pID, - uint256 bType, - uint256 amount - ) public view returns(bool) { - require(activePeriod.contains(pID), "not active"); - require(actInfo[pID].startTime <= block.timestamp, "not start"); - require(actInfo[pID].endTime > block.timestamp, "has end"); - require(!userPid[user].contains(pID), "has bet"); - require(bType > 0 && bType < 3, "type err"); - require(amount >= actInfo[pID].minAmount && amount <= actInfo[pID].maxAmount, "amount err"); - if(actInfo[pID].rewardToken != address(0)) { - require(IERC20(actInfo[pID].rewardToken).allowance(user, address(this)) >= amount, "not approve enough"); - require(IERC20(actInfo[pID].rewardToken).balanceOf(user) >= amount, "not enough"); - } else { - require(user.balance >= amount, "main token err"); - } - - return true; - } - - - function checkRemove(uint256 pID) public view returns(bool) { - require(activePeriod.contains(pID), "not in"); - require(!actInfo[pID].isBet, "has bet"); - - return true; - } - - function checkAdd( - address user, - uint256 startTime, - uint256 endTime, - uint256 minAmount, - uint256 maxAmount - ) public view returns(bool) { - require(user == owner() || user == operator, "no permission"); - require(startTime > block.timestamp, "startTime err"); - require(endTime > startTime, "endTime err"); - require(minAmount > 0 && maxAmount > minAmount, "amount err"); - - return true; - } - - function getStatus(uint256 pID) external view returns(uint256) { - if(!removePeriod.contains(pID) && !activePeriod.contains(pID)) { - return 5; - } else if(removePeriod.contains(pID)) { - return 6; - } else if(block.timestamp < actInfo[pID].startTime) { - return 1; - } else if ( - actInfo[pID].startTime <= block.timestamp && - actInfo[pID].endTime > block.timestamp - ) { - return 2; - } else if (actInfo[pID].endTime <= block.timestamp && actInfo[pID].winType == 0){ - return 3; - } else if(actInfo[pID].winType != 0) { - return 4; - } - return 0; - } - - function getUserPidNum(address user) external view returns(uint256) { - return userPid[user].length(); - } - - function getUserPid(address user, uint256 index) external view returns(uint256) { - return userPid[user].at(index); - } - - function getAUsersNum(uint256 pID) external view returns(uint256) { - return aUsers[pID].length(); - } - - function getAUsers(uint256 pID, uint256 index) external view returns(address) { - return aUsers[pID].at(index); - } - - function getBUsersNum(uint256 pID) external view returns(uint256) { - return bUsers[pID].length(); - } - - function getBUsers(uint256 pID, uint256 index) external view returns(address) { - return bUsers[pID].at(index); - } - - function getActivePeriodNum() external view returns(uint256) { - return activePeriod.length(); - } - - function getActivePeriod(uint256 index) external view returns(uint256) { - return activePeriod.at(index); - } - - function getRemovePeriodNum() external view returns(uint256) { - return removePeriod.length(); - } - - function getRemovePeriod(uint256 index) external view returns(uint256) { - return removePeriod.at(index); - } -} \ No newline at end of file diff --git a/app/api/uploads/ActivityPool-1729820471994-34420655.sol b/app/api/uploads/ActivityPool-1729820471994-34420655.sol deleted file mode 100644 index daf3372..0000000 --- a/app/api/uploads/ActivityPool-1729820471994-34420655.sol +++ /dev/null @@ -1,1648 +0,0 @@ -// SPDX-License-Identifier: MIT -// OpenZeppelin Contracts (last updated v4.7.0) (utils/Address.sol) - -pragma solidity ^0.8.1; - -/** - * @dev Collection of functions related to the address type - */ -library Address { - /** - * @dev Returns true if `account` is a contract. - * - * [IMPORTANT] - * ==== - * It is unsafe to assume that an address for which this function returns - * false is an externally-owned account (EOA) and not a contract. - * - * Among others, `isContract` will return false for the following - * types of addresses: - * - * - an externally-owned account - * - a contract in construction - * - an address where a contract will be created - * - an address where a contract lived, but was destroyed - * ==== - * - * [IMPORTANT] - * ==== - * You shouldn't rely on `isContract` to protect against flash loan attacks! - * - * Preventing calls from contracts is highly discouraged. It breaks composability, breaks support for smart wallets - * like Gnosis Safe, and does not provide security since it can be circumvented by calling from a contract - * constructor. - * ==== - */ - function isContract(address account) internal view returns (bool) { - // This method relies on extcodesize/address.code.length, which returns 0 - // for contracts in construction, since the code is only stored at the end - // of the constructor execution. - - return account.code.length > 0; - } - - /** - * @dev Replacement for Solidity's `transfer`: sends `amount` wei to - * `recipient`, forwarding all available gas and reverting on errors. - * - * https://eips.ethereum.org/EIPS/eip-1884[EIP1884] increases the gas cost - * of certain opcodes, possibly making contracts go over the 2300 gas limit - * imposed by `transfer`, making them unable to receive funds via - * `transfer`. {sendValue} removes this limitation. - * - * https://diligence.consensys.net/posts/2019/09/stop-using-soliditys-transfer-now/[Learn more]. - * - * IMPORTANT: because control is transferred to `recipient`, care must be - * taken to not create reentrancy vulnerabilities. Consider using - * {ReentrancyGuard} or the - * https://solidity.readthedocs.io/en/v0.5.11/security-considerations.html#use-the-checks-effects-interactions-pattern[checks-effects-interactions pattern]. - */ - function sendValue(address payable recipient, uint256 amount) internal { - require(address(this).balance >= amount, "Address: insufficient balance"); - - (bool success, ) = recipient.call{value: amount}(""); - require(success, "Address: unable to send value, recipient may have reverted"); - } - - /** - * @dev Performs a Solidity function call using a low level `call`. A - * plain `call` is an unsafe replacement for a function call: use this - * function instead. - * - * If `target` reverts with a revert reason, it is bubbled up by this - * function (like regular Solidity function calls). - * - * Returns the raw returned data. To convert to the expected return value, - * use https://solidity.readthedocs.io/en/latest/units-and-global-variables.html?highlight=abi.decode#abi-encoding-and-decoding-functions[`abi.decode`]. - * - * Requirements: - * - * - `target` must be a contract. - * - calling `target` with `data` must not revert. - * - * _Available since v3.1._ - */ - function functionCall(address target, bytes memory data) internal returns (bytes memory) { - return functionCallWithValue(target, data, 0, "Address: low-level call failed"); - } - - /** - * @dev Same as {xref-Address-functionCall-address-bytes-}[`functionCall`], but with - * `errorMessage` as a fallback revert reason when `target` reverts. - * - * _Available since v3.1._ - */ - function functionCall( - address target, - bytes memory data, - string memory errorMessage - ) internal returns (bytes memory) { - return functionCallWithValue(target, data, 0, errorMessage); - } - - /** - * @dev Same as {xref-Address-functionCall-address-bytes-}[`functionCall`], - * but also transferring `value` wei to `target`. - * - * Requirements: - * - * - the calling contract must have an ETH balance of at least `value`. - * - the called Solidity function must be `payable`. - * - * _Available since v3.1._ - */ - function functionCallWithValue( - address target, - bytes memory data, - uint256 value - ) internal returns (bytes memory) { - return functionCallWithValue(target, data, value, "Address: low-level call with value failed"); - } - - /** - * @dev Same as {xref-Address-functionCallWithValue-address-bytes-uint256-}[`functionCallWithValue`], but - * with `errorMessage` as a fallback revert reason when `target` reverts. - * - * _Available since v3.1._ - */ - function functionCallWithValue( - address target, - bytes memory data, - uint256 value, - string memory errorMessage - ) internal returns (bytes memory) { - require(address(this).balance >= value, "Address: insufficient balance for call"); - (bool success, bytes memory returndata) = target.call{value: value}(data); - return verifyCallResultFromTarget(target, success, returndata, errorMessage); - } - - /** - * @dev Same as {xref-Address-functionCall-address-bytes-}[`functionCall`], - * but performing a static call. - * - * _Available since v3.3._ - */ - function functionStaticCall(address target, bytes memory data) internal view returns (bytes memory) { - return functionStaticCall(target, data, "Address: low-level static call failed"); - } - - /** - * @dev Same as {xref-Address-functionCall-address-bytes-string-}[`functionCall`], - * but performing a static call. - * - * _Available since v3.3._ - */ - function functionStaticCall( - address target, - bytes memory data, - string memory errorMessage - ) internal view returns (bytes memory) { - (bool success, bytes memory returndata) = target.staticcall(data); - return verifyCallResultFromTarget(target, success, returndata, errorMessage); - } - - /** - * @dev Same as {xref-Address-functionCall-address-bytes-}[`functionCall`], - * but performing a delegate call. - * - * _Available since v3.4._ - */ - function functionDelegateCall(address target, bytes memory data) internal returns (bytes memory) { - return functionDelegateCall(target, data, "Address: low-level delegate call failed"); - } - - /** - * @dev Same as {xref-Address-functionCall-address-bytes-string-}[`functionCall`], - * but performing a delegate call. - * - * _Available since v3.4._ - */ - function functionDelegateCall( - address target, - bytes memory data, - string memory errorMessage - ) internal returns (bytes memory) { - (bool success, bytes memory returndata) = target.delegatecall(data); - return verifyCallResultFromTarget(target, success, returndata, errorMessage); - } - - /** - * @dev Tool to verify that a low level call to smart-contract was successful, and revert (either by bubbling - * the revert reason or using the provided one) in case of unsuccessful call or if target was not a contract. - * - * _Available since v4.8._ - */ - function verifyCallResultFromTarget( - address target, - bool success, - bytes memory returndata, - string memory errorMessage - ) internal view returns (bytes memory) { - if (success) { - if (returndata.length == 0) { - // only check isContract if the call was successful and the return data is empty - // otherwise we already know that it was a contract - require(isContract(target), "Address: call to non-contract"); - } - return returndata; - } else { - _revert(returndata, errorMessage); - } - } - - /** - * @dev Tool to verify that a low level call was successful, and revert if it wasn't, either by bubbling the - * revert reason or using the provided one. - * - * _Available since v4.3._ - */ - function verifyCallResult( - bool success, - bytes memory returndata, - string memory errorMessage - ) internal pure returns (bytes memory) { - if (success) { - return returndata; - } else { - _revert(returndata, errorMessage); - } - } - - function _revert(bytes memory returndata, string memory errorMessage) private pure { - // Look for revert reason and bubble it up if present - if (returndata.length > 0) { - // The easiest way to bubble the revert reason is using memory via assembly - /// @solidity memory-safe-assembly - assembly { - let returndata_size := mload(returndata) - revert(add(32, returndata), returndata_size) - } - } else { - revert(errorMessage); - } - } -} - -// OpenZeppelin Contracts (last updated v4.6.0) (token/ERC20/IERC20.sol) - - - -/** - * @dev Interface of the ERC20 standard as defined in the EIP. - */ -interface IERC20 { - /** - * @dev Emitted when `value` tokens are moved from one account (`from`) to - * another (`to`). - * - * Note that `value` may be zero. - */ - event Transfer(address indexed from, address indexed to, uint256 value); - - /** - * @dev Emitted when the allowance of a `spender` for an `owner` is set by - * a call to {approve}. `value` is the new allowance. - */ - event Approval(address indexed owner, address indexed spender, uint256 value); - - /** - * @dev Returns the amount of tokens in existence. - */ - function totalSupply() external view returns (uint256); - - /** - * @dev Returns the amount of tokens owned by `account`. - */ - function balanceOf(address account) external view returns (uint256); - - /** - * @dev Moves `amount` tokens from the caller's account to `to`. - * - * Returns a boolean value indicating whether the operation succeeded. - * - * Emits a {Transfer} event. - */ - function transfer(address to, uint256 amount) external returns (bool); - - /** - * @dev Returns the remaining number of tokens that `spender` will be - * allowed to spend on behalf of `owner` through {transferFrom}. This is - * zero by default. - * - * This value changes when {approve} or {transferFrom} are called. - */ - function allowance(address owner, address spender) external view returns (uint256); - - /** - * @dev Sets `amount` as the allowance of `spender` over the caller's tokens. - * - * Returns a boolean value indicating whether the operation succeeded. - * - * IMPORTANT: Beware that changing an allowance with this method brings the risk - * that someone may use both the old and the new allowance by unfortunate - * transaction ordering. One possible solution to mitigate this race - * condition is to first reduce the spender's allowance to 0 and set the - * desired value afterwards: - * https://github.com/ethereum/EIPs/issues/20#issuecomment-263524729 - * - * Emits an {Approval} event. - */ - function approve(address spender, uint256 amount) external returns (bool); - - /** - * @dev Moves `amount` tokens from `from` to `to` using the - * allowance mechanism. `amount` is then deducted from the caller's - * allowance. - * - * Returns a boolean value indicating whether the operation succeeded. - * - * Emits a {Transfer} event. - */ - function transferFrom( - address from, - address to, - uint256 amount - ) external returns (bool); - - - function mint(address account_, uint256 amount_) external; - - function burn(uint256 amount) external; - -} - - - - - - - - - - - -/** - * @dev Wrappers over Solidity's arithmetic operations with added overflow - * checks. - * - * Arithmetic operations in Solidity wrap on overflow. This can easily result - * in bugs, because programmers usually assume that an overflow raises an - * error, which is the standard behavior in high level programming languages. - * `SafeMath` restores this intuition by reverting the transaction when an - * operation overflows. - * - * Using this library instead of the unchecked operations eliminates an entire - * class of bugs, so it's recommended to use it always. - */ -library SafeMath { - /** - * @dev Returns the addition of two unsigned integers, reverting on - * overflow. - * - * Counterpart to Solidity's `+` operator. - * - * Requirements: - * - * - Addition cannot overflow. - */ - function add(uint256 a, uint256 b) internal pure returns (uint256) { - uint256 c = a + b; - require(c >= a, "SafeMath: addition overflow"); - - return c; - } - - /** - * @dev Returns the subtraction of two unsigned integers, reverting on - * overflow (when the result is negative). - * - * Counterpart to Solidity's `-` operator. - * - * Requirements: - * - * - Subtraction cannot overflow. - */ - function sub(uint256 a, uint256 b) internal pure returns (uint256) { - return sub(a, b, "SafeMath: subtraction overflow"); - } - - /** - * @dev Returns the subtraction of two unsigned integers, reverting with custom message on - * overflow (when the result is negative). - * - * Counterpart to Solidity's `-` operator. - * - * Requirements: - * - * - Subtraction cannot overflow. - */ - function sub( - uint256 a, - uint256 b, - string memory errorMessage - ) internal pure returns (uint256) { - require(b <= a, errorMessage); - uint256 c = a - b; - - return c; - } - - /** - * @dev Returns the multiplication of two unsigned integers, reverting on - * overflow. - * - * Counterpart to Solidity's `*` operator. - * - * Requirements: - * - * - Multiplication cannot overflow. - */ - function mul(uint256 a, uint256 b) internal pure returns (uint256) { - // Gas optimization: this is cheaper than requiring 'a' not being zero, but the - // benefit is lost if 'b' is also tested. - // See: https://github.com/OpenZeppelin/openzeppelin-contracts/pull/522 - if (a == 0) { - return 0; - } - - uint256 c = a * b; - require(c / a == b, "SafeMath: multiplication overflow"); - - return c; - } - - /** - * @dev Returns the integer division of two unsigned integers. Reverts on - * division by zero. The result is rounded towards zero. - * - * Counterpart to Solidity's `/` operator. Note: this function uses a - * `revert` opcode (which leaves remaining gas untouched) while Solidity - * uses an invalid opcode to revert (consuming all remaining gas). - * - * Requirements: - * - * - The divisor cannot be zero. - */ - function div(uint256 a, uint256 b) internal pure returns (uint256) { - return div(a, b, "SafeMath: division by zero"); - } - - /** - * @dev Returns the integer division of two unsigned integers. Reverts with custom message on - * division by zero. The result is rounded towards zero. - * - * Counterpart to Solidity's `/` operator. Note: this function uses a - * `revert` opcode (which leaves remaining gas untouched) while Solidity - * uses an invalid opcode to revert (consuming all remaining gas). - * - * Requirements: - * - * - The divisor cannot be zero. - */ - function div( - uint256 a, - uint256 b, - string memory errorMessage - ) internal pure returns (uint256) { - require(b > 0, errorMessage); - uint256 c = a / b; - // assert(a == b * c + a % b); // There is no case in which this doesn't hold - - return c; - } - - /** - * @dev Returns the remainder of dividing two unsigned integers. (unsigned integer modulo), - * Reverts when dividing by zero. - * - * Counterpart to Solidity's `%` operator. This function uses a `revert` - * opcode (which leaves remaining gas untouched) while Solidity uses an - * invalid opcode to revert (consuming all remaining gas). - * - * Requirements: - * - * - The divisor cannot be zero. - */ - function mod(uint256 a, uint256 b) internal pure returns (uint256) { - return mod(a, b, "SafeMath: modulo by zero"); - } - - /** - * @dev Returns the remainder of dividing two unsigned integers. (unsigned integer modulo), - * Reverts with custom message when dividing by zero. - * - * Counterpart to Solidity's `%` operator. This function uses a `revert` - * opcode (which leaves remaining gas untouched) while Solidity uses an - * invalid opcode to revert (consuming all remaining gas). - * - * Requirements: - * - * - The divisor cannot be zero. - */ - function mod( - uint256 a, - uint256 b, - string memory errorMessage - ) internal pure returns (uint256) { - require(b != 0, errorMessage); - return a % b; - } - - // babylonian method (https://en.wikipedia.org/wiki/Methods_of_computing_square_roots#Babylonian_method) - function sqrrt(uint256 a) internal pure returns (uint256 c) { - if (a > 3) { - c = a; - uint256 b = add(div(a, 2), 1); - while (b < c) { - c = b; - b = div(add(div(a, b), b), 2); - } - } else if (a != 0) { - c = 1; - } - } - - /* - * Expects percentage to be trailed by 00, - */ - function percentageAmount(uint256 total_, uint8 percentage_) internal pure returns (uint256 percentAmount_) { - return div(mul(total_, percentage_), 1000); - } - - /* - * Expects percentage to be trailed by 00, - */ - function substractPercentage(uint256 total_, uint8 percentageToSub_) internal pure returns (uint256 result_) { - return sub(total_, div(mul(total_, percentageToSub_), 1000)); - } - - function percentageOfTotal(uint256 part_, uint256 total_) internal pure returns (uint256 percent_) { - return div(mul(part_, 100), total_); - } - - /** - * Taken from Hypersonic https://github.com/M2629/HyperSonic/blob/main/Math.sol - * @dev Returns the average of two numbers. The result is rounded towards - * zero. - */ - function average(uint256 a, uint256 b) internal pure returns (uint256) { - // (a + b) / 2 can overflow, so we distribute - return (a / 2) + (b / 2) + (((a % 2) + (b % 2)) / 2); - } - - function quadraticPricing(uint256 payment_, uint256 multiplier_) internal pure returns (uint256) { - return sqrrt(mul(multiplier_, payment_)); - } - - function bondingCurve(uint256 supply_, uint256 multiplier_) internal pure returns (uint256) { - return mul(multiplier_, supply_); - } -} - -// OpenZeppelin Contracts (last updated v4.7.0) (token/ERC20/utils/SafeERC20.sol) - - - - - -// OpenZeppelin Contracts v4.4.1 (token/ERC20/extensions/draft-IERC20Permit.sol) - - - -/** - * @dev Interface of the ERC20 Permit extension allowing approvals to be made via signatures, as defined in - * https://eips.ethereum.org/EIPS/eip-2612[EIP-2612]. - * - * Adds the {permit} method, which can be used to change an account's ERC20 allowance (see {IERC20-allowance}) by - * presenting a message signed by the account. By not relying on {IERC20-approve}, the token holder account doesn't - * need to send a transaction, and thus is not required to hold Ether at all. - */ -interface IERC20Permit { - /** - * @dev Sets `value` as the allowance of `spender` over ``owner``'s tokens, - * given ``owner``'s signed approval. - * - * IMPORTANT: The same issues {IERC20-approve} has related to transaction - * ordering also apply here. - * - * Emits an {Approval} event. - * - * Requirements: - * - * - `spender` cannot be the zero address. - * - `deadline` must be a timestamp in the future. - * - `v`, `r` and `s` must be a valid `secp256k1` signature from `owner` - * over the EIP712-formatted function arguments. - * - the signature must use ``owner``'s current nonce (see {nonces}). - * - * For more information on the signature format, see the - * https://eips.ethereum.org/EIPS/eip-2612#specification[relevant EIP - * section]. - */ - function permit( - address owner, - address spender, - uint256 value, - uint256 deadline, - uint8 v, - bytes32 r, - bytes32 s - ) external; - - /** - * @dev Returns the current nonce for `owner`. This value must be - * included whenever a signature is generated for {permit}. - * - * Every successful call to {permit} increases ``owner``'s nonce by one. This - * prevents a signature from being used multiple times. - */ - function nonces(address owner) external view returns (uint256); - - /** - * @dev Returns the domain separator used in the encoding of the signature for {permit}, as defined by {EIP712}. - */ - // solhint-disable-next-line func-name-mixedcase - function DOMAIN_SEPARATOR() external view returns (bytes32); -} - - - -/** - * @title SafeERC20 - * @dev Wrappers around ERC20 operations that throw on failure (when the token - * contract returns false). Tokens that return no value (and instead revert or - * throw on failure) are also supported, non-reverting calls are assumed to be - * successful. - * To use this library you can add a `using SafeERC20 for IERC20;` statement to your contract, - * which allows you to call the safe operations as `token.safeTransfer(...)`, etc. - */ -library SafeERC20 { - using Address for address; - - function safeTransfer( - IERC20 token, - address to, - uint256 value - ) internal { - _callOptionalReturn(token, abi.encodeWithSelector(token.transfer.selector, to, value)); - } - - function safeTransferFrom( - IERC20 token, - address from, - address to, - uint256 value - ) internal { - _callOptionalReturn(token, abi.encodeWithSelector(token.transferFrom.selector, from, to, value)); - } - - /** - * @dev Deprecated. This function has issues similar to the ones found in - * {IERC20-approve}, and its usage is discouraged. - * - * Whenever possible, use {safeIncreaseAllowance} and - * {safeDecreaseAllowance} instead. - */ - function safeApprove( - IERC20 token, - address spender, - uint256 value - ) internal { - // safeApprove should only be called when setting an initial allowance, - // or when resetting it to zero. To increase and decrease it, use - // 'safeIncreaseAllowance' and 'safeDecreaseAllowance' - require( - (value == 0) || (token.allowance(address(this), spender) == 0), - "SafeERC20: approve from non-zero to non-zero allowance" - ); - _callOptionalReturn(token, abi.encodeWithSelector(token.approve.selector, spender, value)); - } - - function safeIncreaseAllowance( - IERC20 token, - address spender, - uint256 value - ) internal { - uint256 newAllowance = token.allowance(address(this), spender) + value; - _callOptionalReturn(token, abi.encodeWithSelector(token.approve.selector, spender, newAllowance)); - } - - function safeDecreaseAllowance( - IERC20 token, - address spender, - uint256 value - ) internal { - unchecked { - uint256 oldAllowance = token.allowance(address(this), spender); - require(oldAllowance >= value, "SafeERC20: decreased allowance below zero"); - uint256 newAllowance = oldAllowance - value; - _callOptionalReturn(token, abi.encodeWithSelector(token.approve.selector, spender, newAllowance)); - } - } - - function safePermit( - IERC20Permit token, - address owner, - address spender, - uint256 value, - uint256 deadline, - uint8 v, - bytes32 r, - bytes32 s - ) internal { - uint256 nonceBefore = token.nonces(owner); - token.permit(owner, spender, value, deadline, v, r, s); - uint256 nonceAfter = token.nonces(owner); - require(nonceAfter == nonceBefore + 1, "SafeERC20: permit did not succeed"); - } - - /** - * @dev Imitates a Solidity high-level call (i.e. a regular function call to a contract), relaxing the requirement - * on the return value: the return value is optional (but if data is returned, it must not be false). - * @param token The token targeted by the call. - * @param data The call data (encoded using abi.encode or one of its variants). - */ - function _callOptionalReturn(IERC20 token, bytes memory data) private { - // We need to perform a low level call here, to bypass Solidity's return data size checking mechanism, since - // we're implementing it ourselves. We use {Address.functionCall} to perform this call, which verifies that - // the target address contains contract code and also asserts for success in the low-level call. - - bytes memory returndata = address(token).functionCall(data, "SafeERC20: low-level call failed"); - if (returndata.length > 0) { - // Return data is optional - require(abi.decode(returndata, (bool)), "SafeERC20: ERC20 operation did not succeed"); - } - } -} - - - - - - - - - - - - - - -/** - * @dev Provides information about the current execution context, including the - * sender of the transaction and its data. While these are generally available - * via msg.sender and msg.data, they should not be accessed in such a direct - * manner, since when dealing with meta-transactions the account sending and - * paying for execution may not be the actual sender (as far as an application - * is concerned). - * - * This contract is only required for intermediate, library-like contracts. - */ -abstract contract Context { - function _msgSender() internal view virtual returns (address) { - return msg.sender; - } - - function _msgData() internal view virtual returns (bytes calldata) { - return msg.data; - } -} - - -/** - * @dev Contract module which provides a basic access control mechanism, where - * there is an account (an owner) that can be granted exclusive access to - * specific functions. - * - * By default, the owner account will be the one that deploys the contract. This - * can later be changed with {transferOwnership}. - * - * This module is used through inheritance. It will make available the modifier - * `onlyOwner`, which can be applied to your functions to restrict their use to - * the owner. - */ -abstract contract Ownable is Context { - address private _owner; - - event OwnershipTransferred(address indexed previousOwner, address indexed newOwner); - - /** - * @dev Initializes the contract setting the deployer as the initial owner. - */ - constructor() { - _transferOwnership(_msgSender()); - } - - /** - * @dev Throws if called by any account other than the owner. - */ - modifier onlyOwner() { - _checkOwner(); - _; - } - - /** - * @dev Returns the address of the current owner. - */ - function owner() public view virtual returns (address) { - return _owner; - } - - /** - * @dev Throws if the sender is not the owner. - */ - function _checkOwner() internal view virtual { - require(owner() == _msgSender(), "Ownable: caller is not the owner"); - } - - /** - * @dev Leaves the contract without owner. It will not be possible to call - * `onlyOwner` functions anymore. Can only be called by the current owner. - * - * NOTE: Renouncing ownership will leave the contract without an owner, - * thereby removing any functionality that is only available to the owner. - */ - function renounceOwnership() public virtual onlyOwner { - _transferOwnership(address(0)); - } - - /** - * @dev Transfers ownership of the contract to a new account (`newOwner`). - * Can only be called by the current owner. - */ - function transferOwnership(address newOwner) public virtual onlyOwner { - require(newOwner != address(0), "Ownable: new owner is the zero address"); - _transferOwnership(newOwner); - } - - /** - * @dev Transfers ownership of the contract to a new account (`newOwner`). - * Internal function without access restriction. - */ - function _transferOwnership(address newOwner) internal virtual { - address oldOwner = _owner; - _owner = newOwner; - emit OwnershipTransferred(oldOwner, newOwner); - } -} - - -contract Operator is Ownable { - address public operator; - uint256 constant baseRate = 10000; - - modifier onlyOperator { - require(msg.sender == owner() || msg.sender == operator, "no permission"); - _; - } - - function setOperator(address operator_) external onlyOwner { - operator = operator_; - } - - - function getCurrTime() external view returns(uint256) { - return block.timestamp; - } - - function getBlockNum() external view returns(uint256) { - return block.number; - } - -} - - - - - -/** - * @dev Library for managing - * https://en.wikipedia.org/wiki/Set_(abstract_data_type)[sets] of primitive - * types. - * - * Sets have the following properties: - * - * - Elements are added, removed, and checked for existence in constant time - * (O(1)). - * - Elements are enumerated in O(n). No guarantees are made on the ordering. - * - * ``` - * contract Example { - * // Add the library methods - * using EnumerableSet for EnumerableSet.AddressSet; - * - * // Declare a set state variable - * EnumerableSet.AddressSet private mySet; - * } - * ``` - * - * As of v3.3.0, sets of type `bytes32` (`Bytes32Set`), `address` (`AddressSet`) - * and `uint256` (`UintSet`) are supported. - * - * [WARNING] - * ==== - * Trying to delete such a structure from storage will likely result in data corruption, rendering the structure unusable. - * See https://github.com/ethereum/solidity/pull/11843[ethereum/solidity#11843] for more info. - * - * In order to clean an EnumerableSet, you can either remove all elements one by one or create a fresh instance using an array of EnumerableSet. - * ==== - */ - -library EnumerableSet { - // To implement this library for multiple types with as little code - // repetition as possible, we write it in terms of a generic Set type with - // bytes32 values. - // The Set implementation uses private functions, and user-facing - // implementations (such as AddressSet) are just wrappers around the - // underlying Set. - // This means that we can only create new EnumerableSets for types that fit - // in bytes32. - - struct Set { - // Storage of set values - bytes32[] _values; - // Position of the value in the `values` array, plus 1 because index 0 - // means a value is not in the set. - mapping(bytes32 => uint256) _indexes; - } - - /** - * @dev Add a value to a set. O(1). - * - * Returns true if the value was added to the set, that is if it was not - * already present. - */ - function _add(Set storage set, bytes32 value) private returns (bool) { - if (!_contains(set, value)) { - set._values.push(value); - // The value is stored at length-1, but we add 1 to all indexes - // and use 0 as a sentinel value - set._indexes[value] = set._values.length; - return true; - } else { - return false; - } - } - - /** - * @dev Removes a value from a set. O(1). - * - * Returns true if the value was removed from the set, that is if it was - * present. - */ - function _remove(Set storage set, bytes32 value) private returns (bool) { - // We read and store the value's index to prevent multiple reads from the same storage slot - uint256 valueIndex = set._indexes[value]; - - if (valueIndex != 0) { - // Equivalent to contains(set, value) - // To delete an element from the _values array in O(1), we swap the element to delete with the last one in - // the array, and then remove the last element (sometimes called as 'swap and pop'). - // This modifies the order of the array, as noted in {at}. - - uint256 toDeleteIndex = valueIndex - 1; - uint256 lastIndex = set._values.length - 1; - - if (lastIndex != toDeleteIndex) { - bytes32 lastValue = set._values[lastIndex]; - - // Move the last value to the index where the value to delete is - set._values[toDeleteIndex] = lastValue; - // Update the index for the moved value - set._indexes[lastValue] = valueIndex; // Replace lastValue's index to valueIndex - } - - // Delete the slot where the moved value was stored - set._values.pop(); - - // Delete the index for the deleted slot - delete set._indexes[value]; - - return true; - } else { - return false; - } - } - - /** - * @dev Returns true if the value is in the set. O(1). - */ - function _contains(Set storage set, bytes32 value) private view returns (bool) { - return set._indexes[value] != 0; - } - - /** - * @dev Returns the number of values on the set. O(1). - */ - function _length(Set storage set) private view returns (uint256) { - return set._values.length; - } - - /** - * @dev Returns the value stored at position `index` in the set. O(1). - * - * Note that there are no guarantees on the ordering of values inside the - * array, and it may change when more values are added or removed. - * - * Requirements: - * - * - `index` must be strictly less than {length}. - */ - function _at(Set storage set, uint256 index) private view returns (bytes32) { - return set._values[index]; - } - - /** - * @dev Return the entire set in an array - * - * WARNING: This operation will copy the entire storage to memory, which can be quite expensive. This is designed - * to mostly be used by view accessors that are queried without any gas fees. Developers should keep in mind that - * this function has an unbounded cost, and using it as part of a state-changing function may render the function - * uncallable if the set grows to a point where copying to memory consumes too much gas to fit in a block. - */ - function _values(Set storage set) private view returns (bytes32[] memory) { - return set._values; - } - - // Bytes32Set - - struct Bytes32Set { - Set _inner; - } - - /** - * @dev Add a value to a set. O(1). - * - * Returns true if the value was added to the set, that is if it was not - * already present. - */ - function add(Bytes32Set storage set, bytes32 value) internal returns (bool) { - return _add(set._inner, value); - } - - /** - * @dev Removes a value from a set. O(1). - * - * Returns true if the value was removed from the set, that is if it was - * present. - */ - function remove(Bytes32Set storage set, bytes32 value) internal returns (bool) { - return _remove(set._inner, value); - } - - /** - * @dev Returns true if the value is in the set. O(1). - */ - function contains(Bytes32Set storage set, bytes32 value) internal view returns (bool) { - return _contains(set._inner, value); - } - - /** - * @dev Returns the number of values in the set. O(1). - */ - function length(Bytes32Set storage set) internal view returns (uint256) { - return _length(set._inner); - } - - /** - * @dev Returns the value stored at position `index` in the set. O(1). - * - * Note that there are no guarantees on the ordering of values inside the - * array, and it may change when more values are added or removed. - * - * Requirements: - * - * - `index` must be strictly less than {length}. - */ - function at(Bytes32Set storage set, uint256 index) internal view returns (bytes32) { - return _at(set._inner, index); - } - - /** - * @dev Return the entire set in an array - * - * WARNING: This operation will copy the entire storage to memory, which can be quite expensive. This is designed - * to mostly be used by view accessors that are queried without any gas fees. Developers should keep in mind that - * this function has an unbounded cost, and using it as part of a state-changing function may render the function - * uncallable if the set grows to a point where copying to memory consumes too much gas to fit in a block. - */ - function values(Bytes32Set storage set) internal view returns (bytes32[] memory) { - return _values(set._inner); - } - - // AddressSet - - struct AddressSet { - Set _inner; - } - - /** - * @dev Add a value to a set. O(1). - * - * Returns true if the value was added to the set, that is if it was not - * already present. - */ - function add(AddressSet storage set, address value) internal returns (bool) { - return _add(set._inner, bytes32(uint256(uint160(value)))); - } - - /** - * @dev Removes a value from a set. O(1). - * - * Returns true if the value was removed from the set, that is if it was - * present. - */ - function remove(AddressSet storage set, address value) internal returns (bool) { - return _remove(set._inner, bytes32(uint256(uint160(value)))); - } - - /** - * @dev Returns true if the value is in the set. O(1). - */ - function contains(AddressSet storage set, address value) internal view returns (bool) { - return _contains(set._inner, bytes32(uint256(uint160(value)))); - } - - /** - * @dev Returns the number of values in the set. O(1). - */ - function length(AddressSet storage set) internal view returns (uint256) { - return _length(set._inner); - } - - /** - * @dev Returns the value stored at position `index` in the set. O(1). - * - * Note that there are no guarantees on the ordering of values inside the - * array, and it may change when more values are added or removed. - * - * Requirements: - * - * - `index` must be strictly less than {length}. - */ - function at(AddressSet storage set, uint256 index) internal view returns (address) { - return address(uint160(uint256(_at(set._inner, index)))); - } - - /** - * @dev Return the entire set in an array - * - * WARNING: This operation will copy the entire storage to memory, which can be quite expensive. This is designed - * to mostly be used by view accessors that are queried without any gas fees. Developers should keep in mind that - * this function has an unbounded cost, and using it as part of a state-changing function may render the function - * uncallable if the set grows to a point where copying to memory consumes too much gas to fit in a block. - */ - function values(AddressSet storage set) internal view returns (address[] memory) { - bytes32[] memory store = _values(set._inner); - address[] memory result; - - /// @solidity memory-safe-assembly - assembly { - result := store - } - - return result; - } - - // UintSet - - struct UintSet { - Set _inner; - } - - /** - * @dev Add a value to a set. O(1). - * - * Returns true if the value was added to the set, that is if it was not - * already present. - */ - function add(UintSet storage set, uint256 value) internal returns (bool) { - return _add(set._inner, bytes32(value)); - } - - /** - * @dev Removes a value from a set. O(1). - * - * Returns true if the value was removed from the set, that is if it was - * present. - */ - function remove(UintSet storage set, uint256 value) internal returns (bool) { - return _remove(set._inner, bytes32(value)); - } - - /** - * @dev Returns true if the value is in the set. O(1). - */ - function contains(UintSet storage set, uint256 value) internal view returns (bool) { - return _contains(set._inner, bytes32(value)); - } - - /** - * @dev Returns the number of values on the set. O(1). - */ - function length(UintSet storage set) internal view returns (uint256) { - return _length(set._inner); - } - - /** - * @dev Returns the value stored at position `index` in the set. O(1). - * - * Note that there are no guarantees on the ordering of values inside the - * array, and it may change when more values are added or removed. - * - * Requirements: - * - * - `index` must be strictly less than {length}. - */ - function at(UintSet storage set, uint256 index) internal view returns (uint256) { - return uint256(_at(set._inner, index)); - } - - /** - * @dev Return the entire set in an array - * - * WARNING: This operation will copy the entire storage to memory, which can be quite expensive. This is designed - * to mostly be used by view accessors that are queried without any gas fees. Developers should keep in mind that - * this function has an unbounded cost, and using it as part of a state-changing function may render the function - * uncallable if the set grows to a point where copying to memory consumes too much gas to fit in a block. - */ - function values(UintSet storage set) internal view returns (uint256[] memory) { - bytes32[] memory store = _values(set._inner); - uint256[] memory result; - - /// @solidity memory-safe-assembly - assembly { - result := store - } - - return result; - } -} - - -contract ActivityPool is Operator { - using SafeMath for uint256; - using SafeERC20 for IERC20; - using EnumerableSet for EnumerableSet.AddressSet; - using EnumerableSet for EnumerableSet.UintSet; - - event AddNewAct(uint256 id); - event Bet(address user, uint256 pID, uint256 bType, uint256 amount, uint256 time); - event SetPrize(uint256 pID, uint256 bType); - event Claim(address user, uint256 pID, uint256 bType, uint256 amount); - event RemovePeriodAct(uint256 pID); - - uint256 public constant muti = 1e18; - uint256 public periodID; - uint256 public betID; - - struct UserInfo { - address user; - uint256 pID; - uint256 amount; - uint256 betTime; - uint256 bType; - uint256 claimAmount; - } - - struct ActInfo { - string name; - string aName; - string bName; - address rewardToken; - uint256 startTime; - uint256 endTime; - uint256 minAmount; - uint256 maxAmount; - uint256 aAmount; - uint256 bAmount; - uint256 winType; - bool isBet; - } - - struct TimeInfo { - uint256 time; - uint256 aAmount; - uint256 bAmount; - } - - struct BestInfo { - address aUser; - address bUser; - uint256 aBet; - uint256 bBet; - } - - mapping(uint256 => BestInfo) bestInfo; - mapping(uint256 => uint256) public timeID; - mapping(uint256 => mapping(uint256 => TimeInfo)) public timeInfo; - mapping(address => mapping(uint256 => uint256)) public userBet; - mapping(uint256 => UserInfo) public betInfo; - mapping(uint256 => uint256) public perAmount; - mapping(uint256 => ActInfo) public actInfo; - mapping(uint256 => mapping(uint256 => string)) public descripName; - - mapping(address => EnumerableSet.UintSet) userPid; - mapping(uint256 => EnumerableSet.AddressSet) aUsers; - mapping(uint256 => EnumerableSet.AddressSet) bUsers; - EnumerableSet.UintSet activePeriod; - EnumerableSet.UintSet removePeriod; - - function addNewAct( - string memory name, - string memory aName, - string memory bName, - address token, - uint256 startTime, - uint256 endTime, - uint256 minAmount, - uint256 maxAmount - ) external onlyOperator { - - checkAdd(msg.sender, startTime, endTime, minAmount, maxAmount); - uint256 id = ++periodID; - actInfo[id].name = name; - actInfo[id].aName = aName; - actInfo[id].bName = bName; - actInfo[id].startTime = startTime; - actInfo[id].endTime = endTime; - actInfo[id].minAmount = minAmount; - actInfo[id].maxAmount = maxAmount; - actInfo[id].rewardToken = token; - descripName[id][1] = aName; - descripName[id][2] = bName; - activePeriod.add(id); - - emit AddNewAct(id); - } - - - function removePeriodAct(uint256 pID) external onlyOperator { - checkRemove(pID); - - activePeriod.remove(pID); - removePeriod.add(pID); - - emit RemovePeriodAct(pID); - } - - - function bet(uint256 pID, uint256 bType, uint256 amount) external payable { - checkBet(msg.sender, pID, bType, amount); - if(actInfo[pID].rewardToken == address(0)) { - require(msg.value == amount, "value err"); - } else { - require(msg.value == 0, "value amount err"); - } - - if(bType == 1) { - if(amount > bestInfo[pID].aBet) { - bestInfo[pID].aUser = msg.sender; - bestInfo[pID].aBet = amount; - } - } else { - if(amount > bestInfo[pID].bBet) { - bestInfo[pID].bUser = msg.sender; - bestInfo[pID].bBet = amount; - } - } - - userPid[msg.sender].add(pID); - uint256 id = ++betID; - userBet[msg.sender][pID] = id; - - if(bType == 1) { - aUsers[pID].add(msg.sender); - actInfo[pID].aAmount = actInfo[pID].aAmount.add(amount); - } else { - bUsers[pID].add(msg.sender); - actInfo[pID].bAmount = actInfo[pID].bAmount.add(amount); - } - - actInfo[pID].isBet = true; - betInfo[id].user = msg.sender; - betInfo[id].pID = pID; - betInfo[id].amount = amount; - betInfo[id].betTime = block.timestamp; - betInfo[id].bType = bType; - - uint256 tID = ++timeID[pID]; - timeInfo[pID][tID].time = block.timestamp; - timeInfo[pID][tID].aAmount = actInfo[pID].aAmount; - timeInfo[pID][tID].bAmount = actInfo[pID].bAmount; - - if(actInfo[pID].rewardToken != address(0)) { - IERC20(actInfo[pID].rewardToken).safeTransferFrom(msg.sender, address(this), amount); - } - emit Bet(msg.sender, pID, bType, amount, betInfo[id].betTime); - } - - function setPrize(uint256 pID, uint256 bType) external onlyOperator { - checkSetPrize(msg.sender, pID, bType); - - if(block.timestamp <= actInfo[pID].startTime) { - actInfo[pID].startTime = block.timestamp; - - } - actInfo[pID].endTime = block.timestamp; - - actInfo[pID].winType = bType; - perAmount[pID] = getPerAmount(pID, bType); - - emit SetPrize(pID, bType); - } - - function recive() public payable {} - - function claim(uint256 pID) external { - uint256 amount = checkClaim(msg.sender, pID); - - uint256 id = userBet[msg.sender][pID]; - betInfo[id].claimAmount = amount; - if(actInfo[pID].rewardToken != address(0)) { - IERC20(actInfo[pID].rewardToken).safeTransfer(msg.sender, amount); - } else { - payable(msg.sender).transfer(amount); - } - - emit Claim(msg.sender, pID, betInfo[id].bType, amount); - } - - function checkClaim(address user, uint256 pID) public view returns(uint256 amount) { - require(userPid[user].contains(pID), "not bet"); - uint256 id = userBet[user][pID]; - require(betInfo[id].user == user, "not user"); - require(actInfo[pID].winType != 0, "not prize"); - require(betInfo[id].claimAmount == 0, "has claim"); - - if(actInfo[pID].winType != 3) { - require(actInfo[pID].winType == betInfo[id].bType, "not right"); - amount = perAmount[pID].mul(betInfo[id].amount).div(muti); - require(amount > 0, "no amount"); - } else { - amount = betInfo[id].amount; - } - - return amount; - } - - function getActualRate( - address user, - uint256 pID, - uint256 bType, - uint256 amount - ) external view returns(uint256, uint256, bool) { - if(bType < 1 || bType > 2 || !activePeriod.contains(pID)) { - return (0, 0, false); - } else if(userBet[user][pID] != 0 || actInfo[pID].winType != 0 || amount == 0) { - (uint256 ra, uint256 rb) = getRate(pID, timeID[pID]); - return (ra, rb, false); - } else { - (uint256 aAmount, uint256 bAmount) = (actInfo[pID].aAmount, actInfo[pID].bAmount); - if(bType == 1) { - aAmount = aAmount.add(amount); - } else { - bAmount = bAmount.add(amount); - } - - uint256 total = aAmount.add(bAmount); - if(bAmount == 0 && aAmount != 0) { - return (muti, 0, true); - } - if(bAmount != 0 && aAmount == 0) { - return (0, muti, true); - } - return (total.mul(muti).div(aAmount), total.mul(muti).div(bAmount), true); - } - } - - function getRate(uint256 pID, uint256 tID) public view returns(uint256, uint256) { - (uint256 aAmount, uint256 bAmount) = (timeInfo[pID][tID].aAmount, timeInfo[pID][tID].bAmount); - uint256 total = aAmount.add(bAmount); - if(total == 0) { - return (0, 0); - } - if(bAmount == 0 && aAmount != 0) { - return (muti, 0); - } - if(bAmount != 0 && aAmount == 0) { - return (0, muti); - } - return (total.mul(muti).div(aAmount), total.mul(muti).div(bAmount)); - } - - function getBestInfo(uint256 pID) - external - view - returns(address aUser, address bUser, uint256 aBet, uint256 bBet, uint256 aReward, uint256 bReward) - { - aUser = bestInfo[pID].aUser; - bUser = bestInfo[pID].bUser; - aBet = bestInfo[pID].aBet; - bBet = bestInfo[pID].bBet; - aReward = getPerAmount(pID, 1).mul(aBet).div(muti); - bReward = getPerAmount(pID, 2).mul(bBet).div(muti); - } - - function getPerAmount(uint256 pID, uint256 bType) public view returns(uint256) { - uint256 total = actInfo[pID].aAmount.add(actInfo[pID].bAmount); - if(total == 0) { - return 0; - } - - if(actInfo[pID].winType == 3) { - return muti; - } - - if(bType == 1) { - if(actInfo[pID].aAmount == 0 || actInfo[pID].winType == 2) { - return 0; - } - return total.mul(muti).div(actInfo[pID].aAmount); - } - - if(bType == 2) { - if(actInfo[pID].bAmount == 0 || actInfo[pID].winType == 1) { - return 0; - } - return total.mul(muti).div(actInfo[pID].bAmount); - } - - return 0; - - } - - function checkSetPrize(address user, uint256 pID, uint256 bType) public view returns(bool) { - require(user == owner() || user == operator, "no permission"); - require(bType > 0 && bType <= 3, "type err"); - require(activePeriod.contains(pID), "not active"); - require(actInfo[pID].winType == 0, "has set"); - - return true; - } - - function checkBet( - address user, - uint256 pID, - uint256 bType, - uint256 amount - ) public view returns(bool) { - require(activePeriod.contains(pID), "not active"); - require(actInfo[pID].startTime <= block.timestamp, "not start"); - require(actInfo[pID].endTime > block.timestamp, "has end"); - require(!userPid[user].contains(pID), "has bet"); - require(bType > 0 && bType < 3, "type err"); - require(amount >= actInfo[pID].minAmount && amount <= actInfo[pID].maxAmount, "amount err"); - if(actInfo[pID].rewardToken != address(0)) { - require(IERC20(actInfo[pID].rewardToken).allowance(user, address(this)) >= amount, "not approve enough"); - require(IERC20(actInfo[pID].rewardToken).balanceOf(user) >= amount, "not enough"); - } else { - require(user.balance >= amount, "main token err"); - } - - return true; - } - - - function checkRemove(uint256 pID) public view returns(bool) { - require(activePeriod.contains(pID), "not in"); - require(!actInfo[pID].isBet, "has bet"); - - return true; - } - - function checkAdd( - address user, - uint256 startTime, - uint256 endTime, - uint256 minAmount, - uint256 maxAmount - ) public view returns(bool) { - require(user == owner() || user == operator, "no permission"); - require(startTime > block.timestamp, "startTime err"); - require(endTime > startTime, "endTime err"); - require(minAmount > 0 && maxAmount > minAmount, "amount err"); - - return true; - } - - function getStatus(uint256 pID) external view returns(uint256) { - if(!removePeriod.contains(pID) && !activePeriod.contains(pID)) { - return 5; - } else if(removePeriod.contains(pID)) { - return 6; - } else if(block.timestamp < actInfo[pID].startTime) { - return 1; - } else if ( - actInfo[pID].startTime <= block.timestamp && - actInfo[pID].endTime > block.timestamp - ) { - return 2; - } else if (actInfo[pID].endTime <= block.timestamp && actInfo[pID].winType == 0){ - return 3; - } else if(actInfo[pID].winType != 0) { - return 4; - } - return 0; - } - - function getUserPidNum(address user) external view returns(uint256) { - return userPid[user].length(); - } - - function getUserPid(address user, uint256 index) external view returns(uint256) { - return userPid[user].at(index); - } - - function getAUsersNum(uint256 pID) external view returns(uint256) { - return aUsers[pID].length(); - } - - function getAUsers(uint256 pID, uint256 index) external view returns(address) { - return aUsers[pID].at(index); - } - - function getBUsersNum(uint256 pID) external view returns(uint256) { - return bUsers[pID].length(); - } - - function getBUsers(uint256 pID, uint256 index) external view returns(address) { - return bUsers[pID].at(index); - } - - function getActivePeriodNum() external view returns(uint256) { - return activePeriod.length(); - } - - function getActivePeriod(uint256 index) external view returns(uint256) { - return activePeriod.at(index); - } - - function getRemovePeriodNum() external view returns(uint256) { - return removePeriod.length(); - } - - function getRemovePeriod(uint256 index) external view returns(uint256) { - return removePeriod.at(index); - } -} \ No newline at end of file diff --git a/app/api/uploads/ActivityPool-1729820576582-824190408.sol b/app/api/uploads/ActivityPool-1729820576582-824190408.sol deleted file mode 100644 index daf3372..0000000 --- a/app/api/uploads/ActivityPool-1729820576582-824190408.sol +++ /dev/null @@ -1,1648 +0,0 @@ -// SPDX-License-Identifier: MIT -// OpenZeppelin Contracts (last updated v4.7.0) (utils/Address.sol) - -pragma solidity ^0.8.1; - -/** - * @dev Collection of functions related to the address type - */ -library Address { - /** - * @dev Returns true if `account` is a contract. - * - * [IMPORTANT] - * ==== - * It is unsafe to assume that an address for which this function returns - * false is an externally-owned account (EOA) and not a contract. - * - * Among others, `isContract` will return false for the following - * types of addresses: - * - * - an externally-owned account - * - a contract in construction - * - an address where a contract will be created - * - an address where a contract lived, but was destroyed - * ==== - * - * [IMPORTANT] - * ==== - * You shouldn't rely on `isContract` to protect against flash loan attacks! - * - * Preventing calls from contracts is highly discouraged. It breaks composability, breaks support for smart wallets - * like Gnosis Safe, and does not provide security since it can be circumvented by calling from a contract - * constructor. - * ==== - */ - function isContract(address account) internal view returns (bool) { - // This method relies on extcodesize/address.code.length, which returns 0 - // for contracts in construction, since the code is only stored at the end - // of the constructor execution. - - return account.code.length > 0; - } - - /** - * @dev Replacement for Solidity's `transfer`: sends `amount` wei to - * `recipient`, forwarding all available gas and reverting on errors. - * - * https://eips.ethereum.org/EIPS/eip-1884[EIP1884] increases the gas cost - * of certain opcodes, possibly making contracts go over the 2300 gas limit - * imposed by `transfer`, making them unable to receive funds via - * `transfer`. {sendValue} removes this limitation. - * - * https://diligence.consensys.net/posts/2019/09/stop-using-soliditys-transfer-now/[Learn more]. - * - * IMPORTANT: because control is transferred to `recipient`, care must be - * taken to not create reentrancy vulnerabilities. Consider using - * {ReentrancyGuard} or the - * https://solidity.readthedocs.io/en/v0.5.11/security-considerations.html#use-the-checks-effects-interactions-pattern[checks-effects-interactions pattern]. - */ - function sendValue(address payable recipient, uint256 amount) internal { - require(address(this).balance >= amount, "Address: insufficient balance"); - - (bool success, ) = recipient.call{value: amount}(""); - require(success, "Address: unable to send value, recipient may have reverted"); - } - - /** - * @dev Performs a Solidity function call using a low level `call`. A - * plain `call` is an unsafe replacement for a function call: use this - * function instead. - * - * If `target` reverts with a revert reason, it is bubbled up by this - * function (like regular Solidity function calls). - * - * Returns the raw returned data. To convert to the expected return value, - * use https://solidity.readthedocs.io/en/latest/units-and-global-variables.html?highlight=abi.decode#abi-encoding-and-decoding-functions[`abi.decode`]. - * - * Requirements: - * - * - `target` must be a contract. - * - calling `target` with `data` must not revert. - * - * _Available since v3.1._ - */ - function functionCall(address target, bytes memory data) internal returns (bytes memory) { - return functionCallWithValue(target, data, 0, "Address: low-level call failed"); - } - - /** - * @dev Same as {xref-Address-functionCall-address-bytes-}[`functionCall`], but with - * `errorMessage` as a fallback revert reason when `target` reverts. - * - * _Available since v3.1._ - */ - function functionCall( - address target, - bytes memory data, - string memory errorMessage - ) internal returns (bytes memory) { - return functionCallWithValue(target, data, 0, errorMessage); - } - - /** - * @dev Same as {xref-Address-functionCall-address-bytes-}[`functionCall`], - * but also transferring `value` wei to `target`. - * - * Requirements: - * - * - the calling contract must have an ETH balance of at least `value`. - * - the called Solidity function must be `payable`. - * - * _Available since v3.1._ - */ - function functionCallWithValue( - address target, - bytes memory data, - uint256 value - ) internal returns (bytes memory) { - return functionCallWithValue(target, data, value, "Address: low-level call with value failed"); - } - - /** - * @dev Same as {xref-Address-functionCallWithValue-address-bytes-uint256-}[`functionCallWithValue`], but - * with `errorMessage` as a fallback revert reason when `target` reverts. - * - * _Available since v3.1._ - */ - function functionCallWithValue( - address target, - bytes memory data, - uint256 value, - string memory errorMessage - ) internal returns (bytes memory) { - require(address(this).balance >= value, "Address: insufficient balance for call"); - (bool success, bytes memory returndata) = target.call{value: value}(data); - return verifyCallResultFromTarget(target, success, returndata, errorMessage); - } - - /** - * @dev Same as {xref-Address-functionCall-address-bytes-}[`functionCall`], - * but performing a static call. - * - * _Available since v3.3._ - */ - function functionStaticCall(address target, bytes memory data) internal view returns (bytes memory) { - return functionStaticCall(target, data, "Address: low-level static call failed"); - } - - /** - * @dev Same as {xref-Address-functionCall-address-bytes-string-}[`functionCall`], - * but performing a static call. - * - * _Available since v3.3._ - */ - function functionStaticCall( - address target, - bytes memory data, - string memory errorMessage - ) internal view returns (bytes memory) { - (bool success, bytes memory returndata) = target.staticcall(data); - return verifyCallResultFromTarget(target, success, returndata, errorMessage); - } - - /** - * @dev Same as {xref-Address-functionCall-address-bytes-}[`functionCall`], - * but performing a delegate call. - * - * _Available since v3.4._ - */ - function functionDelegateCall(address target, bytes memory data) internal returns (bytes memory) { - return functionDelegateCall(target, data, "Address: low-level delegate call failed"); - } - - /** - * @dev Same as {xref-Address-functionCall-address-bytes-string-}[`functionCall`], - * but performing a delegate call. - * - * _Available since v3.4._ - */ - function functionDelegateCall( - address target, - bytes memory data, - string memory errorMessage - ) internal returns (bytes memory) { - (bool success, bytes memory returndata) = target.delegatecall(data); - return verifyCallResultFromTarget(target, success, returndata, errorMessage); - } - - /** - * @dev Tool to verify that a low level call to smart-contract was successful, and revert (either by bubbling - * the revert reason or using the provided one) in case of unsuccessful call or if target was not a contract. - * - * _Available since v4.8._ - */ - function verifyCallResultFromTarget( - address target, - bool success, - bytes memory returndata, - string memory errorMessage - ) internal view returns (bytes memory) { - if (success) { - if (returndata.length == 0) { - // only check isContract if the call was successful and the return data is empty - // otherwise we already know that it was a contract - require(isContract(target), "Address: call to non-contract"); - } - return returndata; - } else { - _revert(returndata, errorMessage); - } - } - - /** - * @dev Tool to verify that a low level call was successful, and revert if it wasn't, either by bubbling the - * revert reason or using the provided one. - * - * _Available since v4.3._ - */ - function verifyCallResult( - bool success, - bytes memory returndata, - string memory errorMessage - ) internal pure returns (bytes memory) { - if (success) { - return returndata; - } else { - _revert(returndata, errorMessage); - } - } - - function _revert(bytes memory returndata, string memory errorMessage) private pure { - // Look for revert reason and bubble it up if present - if (returndata.length > 0) { - // The easiest way to bubble the revert reason is using memory via assembly - /// @solidity memory-safe-assembly - assembly { - let returndata_size := mload(returndata) - revert(add(32, returndata), returndata_size) - } - } else { - revert(errorMessage); - } - } -} - -// OpenZeppelin Contracts (last updated v4.6.0) (token/ERC20/IERC20.sol) - - - -/** - * @dev Interface of the ERC20 standard as defined in the EIP. - */ -interface IERC20 { - /** - * @dev Emitted when `value` tokens are moved from one account (`from`) to - * another (`to`). - * - * Note that `value` may be zero. - */ - event Transfer(address indexed from, address indexed to, uint256 value); - - /** - * @dev Emitted when the allowance of a `spender` for an `owner` is set by - * a call to {approve}. `value` is the new allowance. - */ - event Approval(address indexed owner, address indexed spender, uint256 value); - - /** - * @dev Returns the amount of tokens in existence. - */ - function totalSupply() external view returns (uint256); - - /** - * @dev Returns the amount of tokens owned by `account`. - */ - function balanceOf(address account) external view returns (uint256); - - /** - * @dev Moves `amount` tokens from the caller's account to `to`. - * - * Returns a boolean value indicating whether the operation succeeded. - * - * Emits a {Transfer} event. - */ - function transfer(address to, uint256 amount) external returns (bool); - - /** - * @dev Returns the remaining number of tokens that `spender` will be - * allowed to spend on behalf of `owner` through {transferFrom}. This is - * zero by default. - * - * This value changes when {approve} or {transferFrom} are called. - */ - function allowance(address owner, address spender) external view returns (uint256); - - /** - * @dev Sets `amount` as the allowance of `spender` over the caller's tokens. - * - * Returns a boolean value indicating whether the operation succeeded. - * - * IMPORTANT: Beware that changing an allowance with this method brings the risk - * that someone may use both the old and the new allowance by unfortunate - * transaction ordering. One possible solution to mitigate this race - * condition is to first reduce the spender's allowance to 0 and set the - * desired value afterwards: - * https://github.com/ethereum/EIPs/issues/20#issuecomment-263524729 - * - * Emits an {Approval} event. - */ - function approve(address spender, uint256 amount) external returns (bool); - - /** - * @dev Moves `amount` tokens from `from` to `to` using the - * allowance mechanism. `amount` is then deducted from the caller's - * allowance. - * - * Returns a boolean value indicating whether the operation succeeded. - * - * Emits a {Transfer} event. - */ - function transferFrom( - address from, - address to, - uint256 amount - ) external returns (bool); - - - function mint(address account_, uint256 amount_) external; - - function burn(uint256 amount) external; - -} - - - - - - - - - - - -/** - * @dev Wrappers over Solidity's arithmetic operations with added overflow - * checks. - * - * Arithmetic operations in Solidity wrap on overflow. This can easily result - * in bugs, because programmers usually assume that an overflow raises an - * error, which is the standard behavior in high level programming languages. - * `SafeMath` restores this intuition by reverting the transaction when an - * operation overflows. - * - * Using this library instead of the unchecked operations eliminates an entire - * class of bugs, so it's recommended to use it always. - */ -library SafeMath { - /** - * @dev Returns the addition of two unsigned integers, reverting on - * overflow. - * - * Counterpart to Solidity's `+` operator. - * - * Requirements: - * - * - Addition cannot overflow. - */ - function add(uint256 a, uint256 b) internal pure returns (uint256) { - uint256 c = a + b; - require(c >= a, "SafeMath: addition overflow"); - - return c; - } - - /** - * @dev Returns the subtraction of two unsigned integers, reverting on - * overflow (when the result is negative). - * - * Counterpart to Solidity's `-` operator. - * - * Requirements: - * - * - Subtraction cannot overflow. - */ - function sub(uint256 a, uint256 b) internal pure returns (uint256) { - return sub(a, b, "SafeMath: subtraction overflow"); - } - - /** - * @dev Returns the subtraction of two unsigned integers, reverting with custom message on - * overflow (when the result is negative). - * - * Counterpart to Solidity's `-` operator. - * - * Requirements: - * - * - Subtraction cannot overflow. - */ - function sub( - uint256 a, - uint256 b, - string memory errorMessage - ) internal pure returns (uint256) { - require(b <= a, errorMessage); - uint256 c = a - b; - - return c; - } - - /** - * @dev Returns the multiplication of two unsigned integers, reverting on - * overflow. - * - * Counterpart to Solidity's `*` operator. - * - * Requirements: - * - * - Multiplication cannot overflow. - */ - function mul(uint256 a, uint256 b) internal pure returns (uint256) { - // Gas optimization: this is cheaper than requiring 'a' not being zero, but the - // benefit is lost if 'b' is also tested. - // See: https://github.com/OpenZeppelin/openzeppelin-contracts/pull/522 - if (a == 0) { - return 0; - } - - uint256 c = a * b; - require(c / a == b, "SafeMath: multiplication overflow"); - - return c; - } - - /** - * @dev Returns the integer division of two unsigned integers. Reverts on - * division by zero. The result is rounded towards zero. - * - * Counterpart to Solidity's `/` operator. Note: this function uses a - * `revert` opcode (which leaves remaining gas untouched) while Solidity - * uses an invalid opcode to revert (consuming all remaining gas). - * - * Requirements: - * - * - The divisor cannot be zero. - */ - function div(uint256 a, uint256 b) internal pure returns (uint256) { - return div(a, b, "SafeMath: division by zero"); - } - - /** - * @dev Returns the integer division of two unsigned integers. Reverts with custom message on - * division by zero. The result is rounded towards zero. - * - * Counterpart to Solidity's `/` operator. Note: this function uses a - * `revert` opcode (which leaves remaining gas untouched) while Solidity - * uses an invalid opcode to revert (consuming all remaining gas). - * - * Requirements: - * - * - The divisor cannot be zero. - */ - function div( - uint256 a, - uint256 b, - string memory errorMessage - ) internal pure returns (uint256) { - require(b > 0, errorMessage); - uint256 c = a / b; - // assert(a == b * c + a % b); // There is no case in which this doesn't hold - - return c; - } - - /** - * @dev Returns the remainder of dividing two unsigned integers. (unsigned integer modulo), - * Reverts when dividing by zero. - * - * Counterpart to Solidity's `%` operator. This function uses a `revert` - * opcode (which leaves remaining gas untouched) while Solidity uses an - * invalid opcode to revert (consuming all remaining gas). - * - * Requirements: - * - * - The divisor cannot be zero. - */ - function mod(uint256 a, uint256 b) internal pure returns (uint256) { - return mod(a, b, "SafeMath: modulo by zero"); - } - - /** - * @dev Returns the remainder of dividing two unsigned integers. (unsigned integer modulo), - * Reverts with custom message when dividing by zero. - * - * Counterpart to Solidity's `%` operator. This function uses a `revert` - * opcode (which leaves remaining gas untouched) while Solidity uses an - * invalid opcode to revert (consuming all remaining gas). - * - * Requirements: - * - * - The divisor cannot be zero. - */ - function mod( - uint256 a, - uint256 b, - string memory errorMessage - ) internal pure returns (uint256) { - require(b != 0, errorMessage); - return a % b; - } - - // babylonian method (https://en.wikipedia.org/wiki/Methods_of_computing_square_roots#Babylonian_method) - function sqrrt(uint256 a) internal pure returns (uint256 c) { - if (a > 3) { - c = a; - uint256 b = add(div(a, 2), 1); - while (b < c) { - c = b; - b = div(add(div(a, b), b), 2); - } - } else if (a != 0) { - c = 1; - } - } - - /* - * Expects percentage to be trailed by 00, - */ - function percentageAmount(uint256 total_, uint8 percentage_) internal pure returns (uint256 percentAmount_) { - return div(mul(total_, percentage_), 1000); - } - - /* - * Expects percentage to be trailed by 00, - */ - function substractPercentage(uint256 total_, uint8 percentageToSub_) internal pure returns (uint256 result_) { - return sub(total_, div(mul(total_, percentageToSub_), 1000)); - } - - function percentageOfTotal(uint256 part_, uint256 total_) internal pure returns (uint256 percent_) { - return div(mul(part_, 100), total_); - } - - /** - * Taken from Hypersonic https://github.com/M2629/HyperSonic/blob/main/Math.sol - * @dev Returns the average of two numbers. The result is rounded towards - * zero. - */ - function average(uint256 a, uint256 b) internal pure returns (uint256) { - // (a + b) / 2 can overflow, so we distribute - return (a / 2) + (b / 2) + (((a % 2) + (b % 2)) / 2); - } - - function quadraticPricing(uint256 payment_, uint256 multiplier_) internal pure returns (uint256) { - return sqrrt(mul(multiplier_, payment_)); - } - - function bondingCurve(uint256 supply_, uint256 multiplier_) internal pure returns (uint256) { - return mul(multiplier_, supply_); - } -} - -// OpenZeppelin Contracts (last updated v4.7.0) (token/ERC20/utils/SafeERC20.sol) - - - - - -// OpenZeppelin Contracts v4.4.1 (token/ERC20/extensions/draft-IERC20Permit.sol) - - - -/** - * @dev Interface of the ERC20 Permit extension allowing approvals to be made via signatures, as defined in - * https://eips.ethereum.org/EIPS/eip-2612[EIP-2612]. - * - * Adds the {permit} method, which can be used to change an account's ERC20 allowance (see {IERC20-allowance}) by - * presenting a message signed by the account. By not relying on {IERC20-approve}, the token holder account doesn't - * need to send a transaction, and thus is not required to hold Ether at all. - */ -interface IERC20Permit { - /** - * @dev Sets `value` as the allowance of `spender` over ``owner``'s tokens, - * given ``owner``'s signed approval. - * - * IMPORTANT: The same issues {IERC20-approve} has related to transaction - * ordering also apply here. - * - * Emits an {Approval} event. - * - * Requirements: - * - * - `spender` cannot be the zero address. - * - `deadline` must be a timestamp in the future. - * - `v`, `r` and `s` must be a valid `secp256k1` signature from `owner` - * over the EIP712-formatted function arguments. - * - the signature must use ``owner``'s current nonce (see {nonces}). - * - * For more information on the signature format, see the - * https://eips.ethereum.org/EIPS/eip-2612#specification[relevant EIP - * section]. - */ - function permit( - address owner, - address spender, - uint256 value, - uint256 deadline, - uint8 v, - bytes32 r, - bytes32 s - ) external; - - /** - * @dev Returns the current nonce for `owner`. This value must be - * included whenever a signature is generated for {permit}. - * - * Every successful call to {permit} increases ``owner``'s nonce by one. This - * prevents a signature from being used multiple times. - */ - function nonces(address owner) external view returns (uint256); - - /** - * @dev Returns the domain separator used in the encoding of the signature for {permit}, as defined by {EIP712}. - */ - // solhint-disable-next-line func-name-mixedcase - function DOMAIN_SEPARATOR() external view returns (bytes32); -} - - - -/** - * @title SafeERC20 - * @dev Wrappers around ERC20 operations that throw on failure (when the token - * contract returns false). Tokens that return no value (and instead revert or - * throw on failure) are also supported, non-reverting calls are assumed to be - * successful. - * To use this library you can add a `using SafeERC20 for IERC20;` statement to your contract, - * which allows you to call the safe operations as `token.safeTransfer(...)`, etc. - */ -library SafeERC20 { - using Address for address; - - function safeTransfer( - IERC20 token, - address to, - uint256 value - ) internal { - _callOptionalReturn(token, abi.encodeWithSelector(token.transfer.selector, to, value)); - } - - function safeTransferFrom( - IERC20 token, - address from, - address to, - uint256 value - ) internal { - _callOptionalReturn(token, abi.encodeWithSelector(token.transferFrom.selector, from, to, value)); - } - - /** - * @dev Deprecated. This function has issues similar to the ones found in - * {IERC20-approve}, and its usage is discouraged. - * - * Whenever possible, use {safeIncreaseAllowance} and - * {safeDecreaseAllowance} instead. - */ - function safeApprove( - IERC20 token, - address spender, - uint256 value - ) internal { - // safeApprove should only be called when setting an initial allowance, - // or when resetting it to zero. To increase and decrease it, use - // 'safeIncreaseAllowance' and 'safeDecreaseAllowance' - require( - (value == 0) || (token.allowance(address(this), spender) == 0), - "SafeERC20: approve from non-zero to non-zero allowance" - ); - _callOptionalReturn(token, abi.encodeWithSelector(token.approve.selector, spender, value)); - } - - function safeIncreaseAllowance( - IERC20 token, - address spender, - uint256 value - ) internal { - uint256 newAllowance = token.allowance(address(this), spender) + value; - _callOptionalReturn(token, abi.encodeWithSelector(token.approve.selector, spender, newAllowance)); - } - - function safeDecreaseAllowance( - IERC20 token, - address spender, - uint256 value - ) internal { - unchecked { - uint256 oldAllowance = token.allowance(address(this), spender); - require(oldAllowance >= value, "SafeERC20: decreased allowance below zero"); - uint256 newAllowance = oldAllowance - value; - _callOptionalReturn(token, abi.encodeWithSelector(token.approve.selector, spender, newAllowance)); - } - } - - function safePermit( - IERC20Permit token, - address owner, - address spender, - uint256 value, - uint256 deadline, - uint8 v, - bytes32 r, - bytes32 s - ) internal { - uint256 nonceBefore = token.nonces(owner); - token.permit(owner, spender, value, deadline, v, r, s); - uint256 nonceAfter = token.nonces(owner); - require(nonceAfter == nonceBefore + 1, "SafeERC20: permit did not succeed"); - } - - /** - * @dev Imitates a Solidity high-level call (i.e. a regular function call to a contract), relaxing the requirement - * on the return value: the return value is optional (but if data is returned, it must not be false). - * @param token The token targeted by the call. - * @param data The call data (encoded using abi.encode or one of its variants). - */ - function _callOptionalReturn(IERC20 token, bytes memory data) private { - // We need to perform a low level call here, to bypass Solidity's return data size checking mechanism, since - // we're implementing it ourselves. We use {Address.functionCall} to perform this call, which verifies that - // the target address contains contract code and also asserts for success in the low-level call. - - bytes memory returndata = address(token).functionCall(data, "SafeERC20: low-level call failed"); - if (returndata.length > 0) { - // Return data is optional - require(abi.decode(returndata, (bool)), "SafeERC20: ERC20 operation did not succeed"); - } - } -} - - - - - - - - - - - - - - -/** - * @dev Provides information about the current execution context, including the - * sender of the transaction and its data. While these are generally available - * via msg.sender and msg.data, they should not be accessed in such a direct - * manner, since when dealing with meta-transactions the account sending and - * paying for execution may not be the actual sender (as far as an application - * is concerned). - * - * This contract is only required for intermediate, library-like contracts. - */ -abstract contract Context { - function _msgSender() internal view virtual returns (address) { - return msg.sender; - } - - function _msgData() internal view virtual returns (bytes calldata) { - return msg.data; - } -} - - -/** - * @dev Contract module which provides a basic access control mechanism, where - * there is an account (an owner) that can be granted exclusive access to - * specific functions. - * - * By default, the owner account will be the one that deploys the contract. This - * can later be changed with {transferOwnership}. - * - * This module is used through inheritance. It will make available the modifier - * `onlyOwner`, which can be applied to your functions to restrict their use to - * the owner. - */ -abstract contract Ownable is Context { - address private _owner; - - event OwnershipTransferred(address indexed previousOwner, address indexed newOwner); - - /** - * @dev Initializes the contract setting the deployer as the initial owner. - */ - constructor() { - _transferOwnership(_msgSender()); - } - - /** - * @dev Throws if called by any account other than the owner. - */ - modifier onlyOwner() { - _checkOwner(); - _; - } - - /** - * @dev Returns the address of the current owner. - */ - function owner() public view virtual returns (address) { - return _owner; - } - - /** - * @dev Throws if the sender is not the owner. - */ - function _checkOwner() internal view virtual { - require(owner() == _msgSender(), "Ownable: caller is not the owner"); - } - - /** - * @dev Leaves the contract without owner. It will not be possible to call - * `onlyOwner` functions anymore. Can only be called by the current owner. - * - * NOTE: Renouncing ownership will leave the contract without an owner, - * thereby removing any functionality that is only available to the owner. - */ - function renounceOwnership() public virtual onlyOwner { - _transferOwnership(address(0)); - } - - /** - * @dev Transfers ownership of the contract to a new account (`newOwner`). - * Can only be called by the current owner. - */ - function transferOwnership(address newOwner) public virtual onlyOwner { - require(newOwner != address(0), "Ownable: new owner is the zero address"); - _transferOwnership(newOwner); - } - - /** - * @dev Transfers ownership of the contract to a new account (`newOwner`). - * Internal function without access restriction. - */ - function _transferOwnership(address newOwner) internal virtual { - address oldOwner = _owner; - _owner = newOwner; - emit OwnershipTransferred(oldOwner, newOwner); - } -} - - -contract Operator is Ownable { - address public operator; - uint256 constant baseRate = 10000; - - modifier onlyOperator { - require(msg.sender == owner() || msg.sender == operator, "no permission"); - _; - } - - function setOperator(address operator_) external onlyOwner { - operator = operator_; - } - - - function getCurrTime() external view returns(uint256) { - return block.timestamp; - } - - function getBlockNum() external view returns(uint256) { - return block.number; - } - -} - - - - - -/** - * @dev Library for managing - * https://en.wikipedia.org/wiki/Set_(abstract_data_type)[sets] of primitive - * types. - * - * Sets have the following properties: - * - * - Elements are added, removed, and checked for existence in constant time - * (O(1)). - * - Elements are enumerated in O(n). No guarantees are made on the ordering. - * - * ``` - * contract Example { - * // Add the library methods - * using EnumerableSet for EnumerableSet.AddressSet; - * - * // Declare a set state variable - * EnumerableSet.AddressSet private mySet; - * } - * ``` - * - * As of v3.3.0, sets of type `bytes32` (`Bytes32Set`), `address` (`AddressSet`) - * and `uint256` (`UintSet`) are supported. - * - * [WARNING] - * ==== - * Trying to delete such a structure from storage will likely result in data corruption, rendering the structure unusable. - * See https://github.com/ethereum/solidity/pull/11843[ethereum/solidity#11843] for more info. - * - * In order to clean an EnumerableSet, you can either remove all elements one by one or create a fresh instance using an array of EnumerableSet. - * ==== - */ - -library EnumerableSet { - // To implement this library for multiple types with as little code - // repetition as possible, we write it in terms of a generic Set type with - // bytes32 values. - // The Set implementation uses private functions, and user-facing - // implementations (such as AddressSet) are just wrappers around the - // underlying Set. - // This means that we can only create new EnumerableSets for types that fit - // in bytes32. - - struct Set { - // Storage of set values - bytes32[] _values; - // Position of the value in the `values` array, plus 1 because index 0 - // means a value is not in the set. - mapping(bytes32 => uint256) _indexes; - } - - /** - * @dev Add a value to a set. O(1). - * - * Returns true if the value was added to the set, that is if it was not - * already present. - */ - function _add(Set storage set, bytes32 value) private returns (bool) { - if (!_contains(set, value)) { - set._values.push(value); - // The value is stored at length-1, but we add 1 to all indexes - // and use 0 as a sentinel value - set._indexes[value] = set._values.length; - return true; - } else { - return false; - } - } - - /** - * @dev Removes a value from a set. O(1). - * - * Returns true if the value was removed from the set, that is if it was - * present. - */ - function _remove(Set storage set, bytes32 value) private returns (bool) { - // We read and store the value's index to prevent multiple reads from the same storage slot - uint256 valueIndex = set._indexes[value]; - - if (valueIndex != 0) { - // Equivalent to contains(set, value) - // To delete an element from the _values array in O(1), we swap the element to delete with the last one in - // the array, and then remove the last element (sometimes called as 'swap and pop'). - // This modifies the order of the array, as noted in {at}. - - uint256 toDeleteIndex = valueIndex - 1; - uint256 lastIndex = set._values.length - 1; - - if (lastIndex != toDeleteIndex) { - bytes32 lastValue = set._values[lastIndex]; - - // Move the last value to the index where the value to delete is - set._values[toDeleteIndex] = lastValue; - // Update the index for the moved value - set._indexes[lastValue] = valueIndex; // Replace lastValue's index to valueIndex - } - - // Delete the slot where the moved value was stored - set._values.pop(); - - // Delete the index for the deleted slot - delete set._indexes[value]; - - return true; - } else { - return false; - } - } - - /** - * @dev Returns true if the value is in the set. O(1). - */ - function _contains(Set storage set, bytes32 value) private view returns (bool) { - return set._indexes[value] != 0; - } - - /** - * @dev Returns the number of values on the set. O(1). - */ - function _length(Set storage set) private view returns (uint256) { - return set._values.length; - } - - /** - * @dev Returns the value stored at position `index` in the set. O(1). - * - * Note that there are no guarantees on the ordering of values inside the - * array, and it may change when more values are added or removed. - * - * Requirements: - * - * - `index` must be strictly less than {length}. - */ - function _at(Set storage set, uint256 index) private view returns (bytes32) { - return set._values[index]; - } - - /** - * @dev Return the entire set in an array - * - * WARNING: This operation will copy the entire storage to memory, which can be quite expensive. This is designed - * to mostly be used by view accessors that are queried without any gas fees. Developers should keep in mind that - * this function has an unbounded cost, and using it as part of a state-changing function may render the function - * uncallable if the set grows to a point where copying to memory consumes too much gas to fit in a block. - */ - function _values(Set storage set) private view returns (bytes32[] memory) { - return set._values; - } - - // Bytes32Set - - struct Bytes32Set { - Set _inner; - } - - /** - * @dev Add a value to a set. O(1). - * - * Returns true if the value was added to the set, that is if it was not - * already present. - */ - function add(Bytes32Set storage set, bytes32 value) internal returns (bool) { - return _add(set._inner, value); - } - - /** - * @dev Removes a value from a set. O(1). - * - * Returns true if the value was removed from the set, that is if it was - * present. - */ - function remove(Bytes32Set storage set, bytes32 value) internal returns (bool) { - return _remove(set._inner, value); - } - - /** - * @dev Returns true if the value is in the set. O(1). - */ - function contains(Bytes32Set storage set, bytes32 value) internal view returns (bool) { - return _contains(set._inner, value); - } - - /** - * @dev Returns the number of values in the set. O(1). - */ - function length(Bytes32Set storage set) internal view returns (uint256) { - return _length(set._inner); - } - - /** - * @dev Returns the value stored at position `index` in the set. O(1). - * - * Note that there are no guarantees on the ordering of values inside the - * array, and it may change when more values are added or removed. - * - * Requirements: - * - * - `index` must be strictly less than {length}. - */ - function at(Bytes32Set storage set, uint256 index) internal view returns (bytes32) { - return _at(set._inner, index); - } - - /** - * @dev Return the entire set in an array - * - * WARNING: This operation will copy the entire storage to memory, which can be quite expensive. This is designed - * to mostly be used by view accessors that are queried without any gas fees. Developers should keep in mind that - * this function has an unbounded cost, and using it as part of a state-changing function may render the function - * uncallable if the set grows to a point where copying to memory consumes too much gas to fit in a block. - */ - function values(Bytes32Set storage set) internal view returns (bytes32[] memory) { - return _values(set._inner); - } - - // AddressSet - - struct AddressSet { - Set _inner; - } - - /** - * @dev Add a value to a set. O(1). - * - * Returns true if the value was added to the set, that is if it was not - * already present. - */ - function add(AddressSet storage set, address value) internal returns (bool) { - return _add(set._inner, bytes32(uint256(uint160(value)))); - } - - /** - * @dev Removes a value from a set. O(1). - * - * Returns true if the value was removed from the set, that is if it was - * present. - */ - function remove(AddressSet storage set, address value) internal returns (bool) { - return _remove(set._inner, bytes32(uint256(uint160(value)))); - } - - /** - * @dev Returns true if the value is in the set. O(1). - */ - function contains(AddressSet storage set, address value) internal view returns (bool) { - return _contains(set._inner, bytes32(uint256(uint160(value)))); - } - - /** - * @dev Returns the number of values in the set. O(1). - */ - function length(AddressSet storage set) internal view returns (uint256) { - return _length(set._inner); - } - - /** - * @dev Returns the value stored at position `index` in the set. O(1). - * - * Note that there are no guarantees on the ordering of values inside the - * array, and it may change when more values are added or removed. - * - * Requirements: - * - * - `index` must be strictly less than {length}. - */ - function at(AddressSet storage set, uint256 index) internal view returns (address) { - return address(uint160(uint256(_at(set._inner, index)))); - } - - /** - * @dev Return the entire set in an array - * - * WARNING: This operation will copy the entire storage to memory, which can be quite expensive. This is designed - * to mostly be used by view accessors that are queried without any gas fees. Developers should keep in mind that - * this function has an unbounded cost, and using it as part of a state-changing function may render the function - * uncallable if the set grows to a point where copying to memory consumes too much gas to fit in a block. - */ - function values(AddressSet storage set) internal view returns (address[] memory) { - bytes32[] memory store = _values(set._inner); - address[] memory result; - - /// @solidity memory-safe-assembly - assembly { - result := store - } - - return result; - } - - // UintSet - - struct UintSet { - Set _inner; - } - - /** - * @dev Add a value to a set. O(1). - * - * Returns true if the value was added to the set, that is if it was not - * already present. - */ - function add(UintSet storage set, uint256 value) internal returns (bool) { - return _add(set._inner, bytes32(value)); - } - - /** - * @dev Removes a value from a set. O(1). - * - * Returns true if the value was removed from the set, that is if it was - * present. - */ - function remove(UintSet storage set, uint256 value) internal returns (bool) { - return _remove(set._inner, bytes32(value)); - } - - /** - * @dev Returns true if the value is in the set. O(1). - */ - function contains(UintSet storage set, uint256 value) internal view returns (bool) { - return _contains(set._inner, bytes32(value)); - } - - /** - * @dev Returns the number of values on the set. O(1). - */ - function length(UintSet storage set) internal view returns (uint256) { - return _length(set._inner); - } - - /** - * @dev Returns the value stored at position `index` in the set. O(1). - * - * Note that there are no guarantees on the ordering of values inside the - * array, and it may change when more values are added or removed. - * - * Requirements: - * - * - `index` must be strictly less than {length}. - */ - function at(UintSet storage set, uint256 index) internal view returns (uint256) { - return uint256(_at(set._inner, index)); - } - - /** - * @dev Return the entire set in an array - * - * WARNING: This operation will copy the entire storage to memory, which can be quite expensive. This is designed - * to mostly be used by view accessors that are queried without any gas fees. Developers should keep in mind that - * this function has an unbounded cost, and using it as part of a state-changing function may render the function - * uncallable if the set grows to a point where copying to memory consumes too much gas to fit in a block. - */ - function values(UintSet storage set) internal view returns (uint256[] memory) { - bytes32[] memory store = _values(set._inner); - uint256[] memory result; - - /// @solidity memory-safe-assembly - assembly { - result := store - } - - return result; - } -} - - -contract ActivityPool is Operator { - using SafeMath for uint256; - using SafeERC20 for IERC20; - using EnumerableSet for EnumerableSet.AddressSet; - using EnumerableSet for EnumerableSet.UintSet; - - event AddNewAct(uint256 id); - event Bet(address user, uint256 pID, uint256 bType, uint256 amount, uint256 time); - event SetPrize(uint256 pID, uint256 bType); - event Claim(address user, uint256 pID, uint256 bType, uint256 amount); - event RemovePeriodAct(uint256 pID); - - uint256 public constant muti = 1e18; - uint256 public periodID; - uint256 public betID; - - struct UserInfo { - address user; - uint256 pID; - uint256 amount; - uint256 betTime; - uint256 bType; - uint256 claimAmount; - } - - struct ActInfo { - string name; - string aName; - string bName; - address rewardToken; - uint256 startTime; - uint256 endTime; - uint256 minAmount; - uint256 maxAmount; - uint256 aAmount; - uint256 bAmount; - uint256 winType; - bool isBet; - } - - struct TimeInfo { - uint256 time; - uint256 aAmount; - uint256 bAmount; - } - - struct BestInfo { - address aUser; - address bUser; - uint256 aBet; - uint256 bBet; - } - - mapping(uint256 => BestInfo) bestInfo; - mapping(uint256 => uint256) public timeID; - mapping(uint256 => mapping(uint256 => TimeInfo)) public timeInfo; - mapping(address => mapping(uint256 => uint256)) public userBet; - mapping(uint256 => UserInfo) public betInfo; - mapping(uint256 => uint256) public perAmount; - mapping(uint256 => ActInfo) public actInfo; - mapping(uint256 => mapping(uint256 => string)) public descripName; - - mapping(address => EnumerableSet.UintSet) userPid; - mapping(uint256 => EnumerableSet.AddressSet) aUsers; - mapping(uint256 => EnumerableSet.AddressSet) bUsers; - EnumerableSet.UintSet activePeriod; - EnumerableSet.UintSet removePeriod; - - function addNewAct( - string memory name, - string memory aName, - string memory bName, - address token, - uint256 startTime, - uint256 endTime, - uint256 minAmount, - uint256 maxAmount - ) external onlyOperator { - - checkAdd(msg.sender, startTime, endTime, minAmount, maxAmount); - uint256 id = ++periodID; - actInfo[id].name = name; - actInfo[id].aName = aName; - actInfo[id].bName = bName; - actInfo[id].startTime = startTime; - actInfo[id].endTime = endTime; - actInfo[id].minAmount = minAmount; - actInfo[id].maxAmount = maxAmount; - actInfo[id].rewardToken = token; - descripName[id][1] = aName; - descripName[id][2] = bName; - activePeriod.add(id); - - emit AddNewAct(id); - } - - - function removePeriodAct(uint256 pID) external onlyOperator { - checkRemove(pID); - - activePeriod.remove(pID); - removePeriod.add(pID); - - emit RemovePeriodAct(pID); - } - - - function bet(uint256 pID, uint256 bType, uint256 amount) external payable { - checkBet(msg.sender, pID, bType, amount); - if(actInfo[pID].rewardToken == address(0)) { - require(msg.value == amount, "value err"); - } else { - require(msg.value == 0, "value amount err"); - } - - if(bType == 1) { - if(amount > bestInfo[pID].aBet) { - bestInfo[pID].aUser = msg.sender; - bestInfo[pID].aBet = amount; - } - } else { - if(amount > bestInfo[pID].bBet) { - bestInfo[pID].bUser = msg.sender; - bestInfo[pID].bBet = amount; - } - } - - userPid[msg.sender].add(pID); - uint256 id = ++betID; - userBet[msg.sender][pID] = id; - - if(bType == 1) { - aUsers[pID].add(msg.sender); - actInfo[pID].aAmount = actInfo[pID].aAmount.add(amount); - } else { - bUsers[pID].add(msg.sender); - actInfo[pID].bAmount = actInfo[pID].bAmount.add(amount); - } - - actInfo[pID].isBet = true; - betInfo[id].user = msg.sender; - betInfo[id].pID = pID; - betInfo[id].amount = amount; - betInfo[id].betTime = block.timestamp; - betInfo[id].bType = bType; - - uint256 tID = ++timeID[pID]; - timeInfo[pID][tID].time = block.timestamp; - timeInfo[pID][tID].aAmount = actInfo[pID].aAmount; - timeInfo[pID][tID].bAmount = actInfo[pID].bAmount; - - if(actInfo[pID].rewardToken != address(0)) { - IERC20(actInfo[pID].rewardToken).safeTransferFrom(msg.sender, address(this), amount); - } - emit Bet(msg.sender, pID, bType, amount, betInfo[id].betTime); - } - - function setPrize(uint256 pID, uint256 bType) external onlyOperator { - checkSetPrize(msg.sender, pID, bType); - - if(block.timestamp <= actInfo[pID].startTime) { - actInfo[pID].startTime = block.timestamp; - - } - actInfo[pID].endTime = block.timestamp; - - actInfo[pID].winType = bType; - perAmount[pID] = getPerAmount(pID, bType); - - emit SetPrize(pID, bType); - } - - function recive() public payable {} - - function claim(uint256 pID) external { - uint256 amount = checkClaim(msg.sender, pID); - - uint256 id = userBet[msg.sender][pID]; - betInfo[id].claimAmount = amount; - if(actInfo[pID].rewardToken != address(0)) { - IERC20(actInfo[pID].rewardToken).safeTransfer(msg.sender, amount); - } else { - payable(msg.sender).transfer(amount); - } - - emit Claim(msg.sender, pID, betInfo[id].bType, amount); - } - - function checkClaim(address user, uint256 pID) public view returns(uint256 amount) { - require(userPid[user].contains(pID), "not bet"); - uint256 id = userBet[user][pID]; - require(betInfo[id].user == user, "not user"); - require(actInfo[pID].winType != 0, "not prize"); - require(betInfo[id].claimAmount == 0, "has claim"); - - if(actInfo[pID].winType != 3) { - require(actInfo[pID].winType == betInfo[id].bType, "not right"); - amount = perAmount[pID].mul(betInfo[id].amount).div(muti); - require(amount > 0, "no amount"); - } else { - amount = betInfo[id].amount; - } - - return amount; - } - - function getActualRate( - address user, - uint256 pID, - uint256 bType, - uint256 amount - ) external view returns(uint256, uint256, bool) { - if(bType < 1 || bType > 2 || !activePeriod.contains(pID)) { - return (0, 0, false); - } else if(userBet[user][pID] != 0 || actInfo[pID].winType != 0 || amount == 0) { - (uint256 ra, uint256 rb) = getRate(pID, timeID[pID]); - return (ra, rb, false); - } else { - (uint256 aAmount, uint256 bAmount) = (actInfo[pID].aAmount, actInfo[pID].bAmount); - if(bType == 1) { - aAmount = aAmount.add(amount); - } else { - bAmount = bAmount.add(amount); - } - - uint256 total = aAmount.add(bAmount); - if(bAmount == 0 && aAmount != 0) { - return (muti, 0, true); - } - if(bAmount != 0 && aAmount == 0) { - return (0, muti, true); - } - return (total.mul(muti).div(aAmount), total.mul(muti).div(bAmount), true); - } - } - - function getRate(uint256 pID, uint256 tID) public view returns(uint256, uint256) { - (uint256 aAmount, uint256 bAmount) = (timeInfo[pID][tID].aAmount, timeInfo[pID][tID].bAmount); - uint256 total = aAmount.add(bAmount); - if(total == 0) { - return (0, 0); - } - if(bAmount == 0 && aAmount != 0) { - return (muti, 0); - } - if(bAmount != 0 && aAmount == 0) { - return (0, muti); - } - return (total.mul(muti).div(aAmount), total.mul(muti).div(bAmount)); - } - - function getBestInfo(uint256 pID) - external - view - returns(address aUser, address bUser, uint256 aBet, uint256 bBet, uint256 aReward, uint256 bReward) - { - aUser = bestInfo[pID].aUser; - bUser = bestInfo[pID].bUser; - aBet = bestInfo[pID].aBet; - bBet = bestInfo[pID].bBet; - aReward = getPerAmount(pID, 1).mul(aBet).div(muti); - bReward = getPerAmount(pID, 2).mul(bBet).div(muti); - } - - function getPerAmount(uint256 pID, uint256 bType) public view returns(uint256) { - uint256 total = actInfo[pID].aAmount.add(actInfo[pID].bAmount); - if(total == 0) { - return 0; - } - - if(actInfo[pID].winType == 3) { - return muti; - } - - if(bType == 1) { - if(actInfo[pID].aAmount == 0 || actInfo[pID].winType == 2) { - return 0; - } - return total.mul(muti).div(actInfo[pID].aAmount); - } - - if(bType == 2) { - if(actInfo[pID].bAmount == 0 || actInfo[pID].winType == 1) { - return 0; - } - return total.mul(muti).div(actInfo[pID].bAmount); - } - - return 0; - - } - - function checkSetPrize(address user, uint256 pID, uint256 bType) public view returns(bool) { - require(user == owner() || user == operator, "no permission"); - require(bType > 0 && bType <= 3, "type err"); - require(activePeriod.contains(pID), "not active"); - require(actInfo[pID].winType == 0, "has set"); - - return true; - } - - function checkBet( - address user, - uint256 pID, - uint256 bType, - uint256 amount - ) public view returns(bool) { - require(activePeriod.contains(pID), "not active"); - require(actInfo[pID].startTime <= block.timestamp, "not start"); - require(actInfo[pID].endTime > block.timestamp, "has end"); - require(!userPid[user].contains(pID), "has bet"); - require(bType > 0 && bType < 3, "type err"); - require(amount >= actInfo[pID].minAmount && amount <= actInfo[pID].maxAmount, "amount err"); - if(actInfo[pID].rewardToken != address(0)) { - require(IERC20(actInfo[pID].rewardToken).allowance(user, address(this)) >= amount, "not approve enough"); - require(IERC20(actInfo[pID].rewardToken).balanceOf(user) >= amount, "not enough"); - } else { - require(user.balance >= amount, "main token err"); - } - - return true; - } - - - function checkRemove(uint256 pID) public view returns(bool) { - require(activePeriod.contains(pID), "not in"); - require(!actInfo[pID].isBet, "has bet"); - - return true; - } - - function checkAdd( - address user, - uint256 startTime, - uint256 endTime, - uint256 minAmount, - uint256 maxAmount - ) public view returns(bool) { - require(user == owner() || user == operator, "no permission"); - require(startTime > block.timestamp, "startTime err"); - require(endTime > startTime, "endTime err"); - require(minAmount > 0 && maxAmount > minAmount, "amount err"); - - return true; - } - - function getStatus(uint256 pID) external view returns(uint256) { - if(!removePeriod.contains(pID) && !activePeriod.contains(pID)) { - return 5; - } else if(removePeriod.contains(pID)) { - return 6; - } else if(block.timestamp < actInfo[pID].startTime) { - return 1; - } else if ( - actInfo[pID].startTime <= block.timestamp && - actInfo[pID].endTime > block.timestamp - ) { - return 2; - } else if (actInfo[pID].endTime <= block.timestamp && actInfo[pID].winType == 0){ - return 3; - } else if(actInfo[pID].winType != 0) { - return 4; - } - return 0; - } - - function getUserPidNum(address user) external view returns(uint256) { - return userPid[user].length(); - } - - function getUserPid(address user, uint256 index) external view returns(uint256) { - return userPid[user].at(index); - } - - function getAUsersNum(uint256 pID) external view returns(uint256) { - return aUsers[pID].length(); - } - - function getAUsers(uint256 pID, uint256 index) external view returns(address) { - return aUsers[pID].at(index); - } - - function getBUsersNum(uint256 pID) external view returns(uint256) { - return bUsers[pID].length(); - } - - function getBUsers(uint256 pID, uint256 index) external view returns(address) { - return bUsers[pID].at(index); - } - - function getActivePeriodNum() external view returns(uint256) { - return activePeriod.length(); - } - - function getActivePeriod(uint256 index) external view returns(uint256) { - return activePeriod.at(index); - } - - function getRemovePeriodNum() external view returns(uint256) { - return removePeriod.length(); - } - - function getRemovePeriod(uint256 index) external view returns(uint256) { - return removePeriod.at(index); - } -} \ No newline at end of file diff --git a/app/api/uploads/ActivityPool-1729821244300-939222585.sol b/app/api/uploads/ActivityPool-1729821244300-939222585.sol deleted file mode 100644 index daf3372..0000000 --- a/app/api/uploads/ActivityPool-1729821244300-939222585.sol +++ /dev/null @@ -1,1648 +0,0 @@ -// SPDX-License-Identifier: MIT -// OpenZeppelin Contracts (last updated v4.7.0) (utils/Address.sol) - -pragma solidity ^0.8.1; - -/** - * @dev Collection of functions related to the address type - */ -library Address { - /** - * @dev Returns true if `account` is a contract. - * - * [IMPORTANT] - * ==== - * It is unsafe to assume that an address for which this function returns - * false is an externally-owned account (EOA) and not a contract. - * - * Among others, `isContract` will return false for the following - * types of addresses: - * - * - an externally-owned account - * - a contract in construction - * - an address where a contract will be created - * - an address where a contract lived, but was destroyed - * ==== - * - * [IMPORTANT] - * ==== - * You shouldn't rely on `isContract` to protect against flash loan attacks! - * - * Preventing calls from contracts is highly discouraged. It breaks composability, breaks support for smart wallets - * like Gnosis Safe, and does not provide security since it can be circumvented by calling from a contract - * constructor. - * ==== - */ - function isContract(address account) internal view returns (bool) { - // This method relies on extcodesize/address.code.length, which returns 0 - // for contracts in construction, since the code is only stored at the end - // of the constructor execution. - - return account.code.length > 0; - } - - /** - * @dev Replacement for Solidity's `transfer`: sends `amount` wei to - * `recipient`, forwarding all available gas and reverting on errors. - * - * https://eips.ethereum.org/EIPS/eip-1884[EIP1884] increases the gas cost - * of certain opcodes, possibly making contracts go over the 2300 gas limit - * imposed by `transfer`, making them unable to receive funds via - * `transfer`. {sendValue} removes this limitation. - * - * https://diligence.consensys.net/posts/2019/09/stop-using-soliditys-transfer-now/[Learn more]. - * - * IMPORTANT: because control is transferred to `recipient`, care must be - * taken to not create reentrancy vulnerabilities. Consider using - * {ReentrancyGuard} or the - * https://solidity.readthedocs.io/en/v0.5.11/security-considerations.html#use-the-checks-effects-interactions-pattern[checks-effects-interactions pattern]. - */ - function sendValue(address payable recipient, uint256 amount) internal { - require(address(this).balance >= amount, "Address: insufficient balance"); - - (bool success, ) = recipient.call{value: amount}(""); - require(success, "Address: unable to send value, recipient may have reverted"); - } - - /** - * @dev Performs a Solidity function call using a low level `call`. A - * plain `call` is an unsafe replacement for a function call: use this - * function instead. - * - * If `target` reverts with a revert reason, it is bubbled up by this - * function (like regular Solidity function calls). - * - * Returns the raw returned data. To convert to the expected return value, - * use https://solidity.readthedocs.io/en/latest/units-and-global-variables.html?highlight=abi.decode#abi-encoding-and-decoding-functions[`abi.decode`]. - * - * Requirements: - * - * - `target` must be a contract. - * - calling `target` with `data` must not revert. - * - * _Available since v3.1._ - */ - function functionCall(address target, bytes memory data) internal returns (bytes memory) { - return functionCallWithValue(target, data, 0, "Address: low-level call failed"); - } - - /** - * @dev Same as {xref-Address-functionCall-address-bytes-}[`functionCall`], but with - * `errorMessage` as a fallback revert reason when `target` reverts. - * - * _Available since v3.1._ - */ - function functionCall( - address target, - bytes memory data, - string memory errorMessage - ) internal returns (bytes memory) { - return functionCallWithValue(target, data, 0, errorMessage); - } - - /** - * @dev Same as {xref-Address-functionCall-address-bytes-}[`functionCall`], - * but also transferring `value` wei to `target`. - * - * Requirements: - * - * - the calling contract must have an ETH balance of at least `value`. - * - the called Solidity function must be `payable`. - * - * _Available since v3.1._ - */ - function functionCallWithValue( - address target, - bytes memory data, - uint256 value - ) internal returns (bytes memory) { - return functionCallWithValue(target, data, value, "Address: low-level call with value failed"); - } - - /** - * @dev Same as {xref-Address-functionCallWithValue-address-bytes-uint256-}[`functionCallWithValue`], but - * with `errorMessage` as a fallback revert reason when `target` reverts. - * - * _Available since v3.1._ - */ - function functionCallWithValue( - address target, - bytes memory data, - uint256 value, - string memory errorMessage - ) internal returns (bytes memory) { - require(address(this).balance >= value, "Address: insufficient balance for call"); - (bool success, bytes memory returndata) = target.call{value: value}(data); - return verifyCallResultFromTarget(target, success, returndata, errorMessage); - } - - /** - * @dev Same as {xref-Address-functionCall-address-bytes-}[`functionCall`], - * but performing a static call. - * - * _Available since v3.3._ - */ - function functionStaticCall(address target, bytes memory data) internal view returns (bytes memory) { - return functionStaticCall(target, data, "Address: low-level static call failed"); - } - - /** - * @dev Same as {xref-Address-functionCall-address-bytes-string-}[`functionCall`], - * but performing a static call. - * - * _Available since v3.3._ - */ - function functionStaticCall( - address target, - bytes memory data, - string memory errorMessage - ) internal view returns (bytes memory) { - (bool success, bytes memory returndata) = target.staticcall(data); - return verifyCallResultFromTarget(target, success, returndata, errorMessage); - } - - /** - * @dev Same as {xref-Address-functionCall-address-bytes-}[`functionCall`], - * but performing a delegate call. - * - * _Available since v3.4._ - */ - function functionDelegateCall(address target, bytes memory data) internal returns (bytes memory) { - return functionDelegateCall(target, data, "Address: low-level delegate call failed"); - } - - /** - * @dev Same as {xref-Address-functionCall-address-bytes-string-}[`functionCall`], - * but performing a delegate call. - * - * _Available since v3.4._ - */ - function functionDelegateCall( - address target, - bytes memory data, - string memory errorMessage - ) internal returns (bytes memory) { - (bool success, bytes memory returndata) = target.delegatecall(data); - return verifyCallResultFromTarget(target, success, returndata, errorMessage); - } - - /** - * @dev Tool to verify that a low level call to smart-contract was successful, and revert (either by bubbling - * the revert reason or using the provided one) in case of unsuccessful call or if target was not a contract. - * - * _Available since v4.8._ - */ - function verifyCallResultFromTarget( - address target, - bool success, - bytes memory returndata, - string memory errorMessage - ) internal view returns (bytes memory) { - if (success) { - if (returndata.length == 0) { - // only check isContract if the call was successful and the return data is empty - // otherwise we already know that it was a contract - require(isContract(target), "Address: call to non-contract"); - } - return returndata; - } else { - _revert(returndata, errorMessage); - } - } - - /** - * @dev Tool to verify that a low level call was successful, and revert if it wasn't, either by bubbling the - * revert reason or using the provided one. - * - * _Available since v4.3._ - */ - function verifyCallResult( - bool success, - bytes memory returndata, - string memory errorMessage - ) internal pure returns (bytes memory) { - if (success) { - return returndata; - } else { - _revert(returndata, errorMessage); - } - } - - function _revert(bytes memory returndata, string memory errorMessage) private pure { - // Look for revert reason and bubble it up if present - if (returndata.length > 0) { - // The easiest way to bubble the revert reason is using memory via assembly - /// @solidity memory-safe-assembly - assembly { - let returndata_size := mload(returndata) - revert(add(32, returndata), returndata_size) - } - } else { - revert(errorMessage); - } - } -} - -// OpenZeppelin Contracts (last updated v4.6.0) (token/ERC20/IERC20.sol) - - - -/** - * @dev Interface of the ERC20 standard as defined in the EIP. - */ -interface IERC20 { - /** - * @dev Emitted when `value` tokens are moved from one account (`from`) to - * another (`to`). - * - * Note that `value` may be zero. - */ - event Transfer(address indexed from, address indexed to, uint256 value); - - /** - * @dev Emitted when the allowance of a `spender` for an `owner` is set by - * a call to {approve}. `value` is the new allowance. - */ - event Approval(address indexed owner, address indexed spender, uint256 value); - - /** - * @dev Returns the amount of tokens in existence. - */ - function totalSupply() external view returns (uint256); - - /** - * @dev Returns the amount of tokens owned by `account`. - */ - function balanceOf(address account) external view returns (uint256); - - /** - * @dev Moves `amount` tokens from the caller's account to `to`. - * - * Returns a boolean value indicating whether the operation succeeded. - * - * Emits a {Transfer} event. - */ - function transfer(address to, uint256 amount) external returns (bool); - - /** - * @dev Returns the remaining number of tokens that `spender` will be - * allowed to spend on behalf of `owner` through {transferFrom}. This is - * zero by default. - * - * This value changes when {approve} or {transferFrom} are called. - */ - function allowance(address owner, address spender) external view returns (uint256); - - /** - * @dev Sets `amount` as the allowance of `spender` over the caller's tokens. - * - * Returns a boolean value indicating whether the operation succeeded. - * - * IMPORTANT: Beware that changing an allowance with this method brings the risk - * that someone may use both the old and the new allowance by unfortunate - * transaction ordering. One possible solution to mitigate this race - * condition is to first reduce the spender's allowance to 0 and set the - * desired value afterwards: - * https://github.com/ethereum/EIPs/issues/20#issuecomment-263524729 - * - * Emits an {Approval} event. - */ - function approve(address spender, uint256 amount) external returns (bool); - - /** - * @dev Moves `amount` tokens from `from` to `to` using the - * allowance mechanism. `amount` is then deducted from the caller's - * allowance. - * - * Returns a boolean value indicating whether the operation succeeded. - * - * Emits a {Transfer} event. - */ - function transferFrom( - address from, - address to, - uint256 amount - ) external returns (bool); - - - function mint(address account_, uint256 amount_) external; - - function burn(uint256 amount) external; - -} - - - - - - - - - - - -/** - * @dev Wrappers over Solidity's arithmetic operations with added overflow - * checks. - * - * Arithmetic operations in Solidity wrap on overflow. This can easily result - * in bugs, because programmers usually assume that an overflow raises an - * error, which is the standard behavior in high level programming languages. - * `SafeMath` restores this intuition by reverting the transaction when an - * operation overflows. - * - * Using this library instead of the unchecked operations eliminates an entire - * class of bugs, so it's recommended to use it always. - */ -library SafeMath { - /** - * @dev Returns the addition of two unsigned integers, reverting on - * overflow. - * - * Counterpart to Solidity's `+` operator. - * - * Requirements: - * - * - Addition cannot overflow. - */ - function add(uint256 a, uint256 b) internal pure returns (uint256) { - uint256 c = a + b; - require(c >= a, "SafeMath: addition overflow"); - - return c; - } - - /** - * @dev Returns the subtraction of two unsigned integers, reverting on - * overflow (when the result is negative). - * - * Counterpart to Solidity's `-` operator. - * - * Requirements: - * - * - Subtraction cannot overflow. - */ - function sub(uint256 a, uint256 b) internal pure returns (uint256) { - return sub(a, b, "SafeMath: subtraction overflow"); - } - - /** - * @dev Returns the subtraction of two unsigned integers, reverting with custom message on - * overflow (when the result is negative). - * - * Counterpart to Solidity's `-` operator. - * - * Requirements: - * - * - Subtraction cannot overflow. - */ - function sub( - uint256 a, - uint256 b, - string memory errorMessage - ) internal pure returns (uint256) { - require(b <= a, errorMessage); - uint256 c = a - b; - - return c; - } - - /** - * @dev Returns the multiplication of two unsigned integers, reverting on - * overflow. - * - * Counterpart to Solidity's `*` operator. - * - * Requirements: - * - * - Multiplication cannot overflow. - */ - function mul(uint256 a, uint256 b) internal pure returns (uint256) { - // Gas optimization: this is cheaper than requiring 'a' not being zero, but the - // benefit is lost if 'b' is also tested. - // See: https://github.com/OpenZeppelin/openzeppelin-contracts/pull/522 - if (a == 0) { - return 0; - } - - uint256 c = a * b; - require(c / a == b, "SafeMath: multiplication overflow"); - - return c; - } - - /** - * @dev Returns the integer division of two unsigned integers. Reverts on - * division by zero. The result is rounded towards zero. - * - * Counterpart to Solidity's `/` operator. Note: this function uses a - * `revert` opcode (which leaves remaining gas untouched) while Solidity - * uses an invalid opcode to revert (consuming all remaining gas). - * - * Requirements: - * - * - The divisor cannot be zero. - */ - function div(uint256 a, uint256 b) internal pure returns (uint256) { - return div(a, b, "SafeMath: division by zero"); - } - - /** - * @dev Returns the integer division of two unsigned integers. Reverts with custom message on - * division by zero. The result is rounded towards zero. - * - * Counterpart to Solidity's `/` operator. Note: this function uses a - * `revert` opcode (which leaves remaining gas untouched) while Solidity - * uses an invalid opcode to revert (consuming all remaining gas). - * - * Requirements: - * - * - The divisor cannot be zero. - */ - function div( - uint256 a, - uint256 b, - string memory errorMessage - ) internal pure returns (uint256) { - require(b > 0, errorMessage); - uint256 c = a / b; - // assert(a == b * c + a % b); // There is no case in which this doesn't hold - - return c; - } - - /** - * @dev Returns the remainder of dividing two unsigned integers. (unsigned integer modulo), - * Reverts when dividing by zero. - * - * Counterpart to Solidity's `%` operator. This function uses a `revert` - * opcode (which leaves remaining gas untouched) while Solidity uses an - * invalid opcode to revert (consuming all remaining gas). - * - * Requirements: - * - * - The divisor cannot be zero. - */ - function mod(uint256 a, uint256 b) internal pure returns (uint256) { - return mod(a, b, "SafeMath: modulo by zero"); - } - - /** - * @dev Returns the remainder of dividing two unsigned integers. (unsigned integer modulo), - * Reverts with custom message when dividing by zero. - * - * Counterpart to Solidity's `%` operator. This function uses a `revert` - * opcode (which leaves remaining gas untouched) while Solidity uses an - * invalid opcode to revert (consuming all remaining gas). - * - * Requirements: - * - * - The divisor cannot be zero. - */ - function mod( - uint256 a, - uint256 b, - string memory errorMessage - ) internal pure returns (uint256) { - require(b != 0, errorMessage); - return a % b; - } - - // babylonian method (https://en.wikipedia.org/wiki/Methods_of_computing_square_roots#Babylonian_method) - function sqrrt(uint256 a) internal pure returns (uint256 c) { - if (a > 3) { - c = a; - uint256 b = add(div(a, 2), 1); - while (b < c) { - c = b; - b = div(add(div(a, b), b), 2); - } - } else if (a != 0) { - c = 1; - } - } - - /* - * Expects percentage to be trailed by 00, - */ - function percentageAmount(uint256 total_, uint8 percentage_) internal pure returns (uint256 percentAmount_) { - return div(mul(total_, percentage_), 1000); - } - - /* - * Expects percentage to be trailed by 00, - */ - function substractPercentage(uint256 total_, uint8 percentageToSub_) internal pure returns (uint256 result_) { - return sub(total_, div(mul(total_, percentageToSub_), 1000)); - } - - function percentageOfTotal(uint256 part_, uint256 total_) internal pure returns (uint256 percent_) { - return div(mul(part_, 100), total_); - } - - /** - * Taken from Hypersonic https://github.com/M2629/HyperSonic/blob/main/Math.sol - * @dev Returns the average of two numbers. The result is rounded towards - * zero. - */ - function average(uint256 a, uint256 b) internal pure returns (uint256) { - // (a + b) / 2 can overflow, so we distribute - return (a / 2) + (b / 2) + (((a % 2) + (b % 2)) / 2); - } - - function quadraticPricing(uint256 payment_, uint256 multiplier_) internal pure returns (uint256) { - return sqrrt(mul(multiplier_, payment_)); - } - - function bondingCurve(uint256 supply_, uint256 multiplier_) internal pure returns (uint256) { - return mul(multiplier_, supply_); - } -} - -// OpenZeppelin Contracts (last updated v4.7.0) (token/ERC20/utils/SafeERC20.sol) - - - - - -// OpenZeppelin Contracts v4.4.1 (token/ERC20/extensions/draft-IERC20Permit.sol) - - - -/** - * @dev Interface of the ERC20 Permit extension allowing approvals to be made via signatures, as defined in - * https://eips.ethereum.org/EIPS/eip-2612[EIP-2612]. - * - * Adds the {permit} method, which can be used to change an account's ERC20 allowance (see {IERC20-allowance}) by - * presenting a message signed by the account. By not relying on {IERC20-approve}, the token holder account doesn't - * need to send a transaction, and thus is not required to hold Ether at all. - */ -interface IERC20Permit { - /** - * @dev Sets `value` as the allowance of `spender` over ``owner``'s tokens, - * given ``owner``'s signed approval. - * - * IMPORTANT: The same issues {IERC20-approve} has related to transaction - * ordering also apply here. - * - * Emits an {Approval} event. - * - * Requirements: - * - * - `spender` cannot be the zero address. - * - `deadline` must be a timestamp in the future. - * - `v`, `r` and `s` must be a valid `secp256k1` signature from `owner` - * over the EIP712-formatted function arguments. - * - the signature must use ``owner``'s current nonce (see {nonces}). - * - * For more information on the signature format, see the - * https://eips.ethereum.org/EIPS/eip-2612#specification[relevant EIP - * section]. - */ - function permit( - address owner, - address spender, - uint256 value, - uint256 deadline, - uint8 v, - bytes32 r, - bytes32 s - ) external; - - /** - * @dev Returns the current nonce for `owner`. This value must be - * included whenever a signature is generated for {permit}. - * - * Every successful call to {permit} increases ``owner``'s nonce by one. This - * prevents a signature from being used multiple times. - */ - function nonces(address owner) external view returns (uint256); - - /** - * @dev Returns the domain separator used in the encoding of the signature for {permit}, as defined by {EIP712}. - */ - // solhint-disable-next-line func-name-mixedcase - function DOMAIN_SEPARATOR() external view returns (bytes32); -} - - - -/** - * @title SafeERC20 - * @dev Wrappers around ERC20 operations that throw on failure (when the token - * contract returns false). Tokens that return no value (and instead revert or - * throw on failure) are also supported, non-reverting calls are assumed to be - * successful. - * To use this library you can add a `using SafeERC20 for IERC20;` statement to your contract, - * which allows you to call the safe operations as `token.safeTransfer(...)`, etc. - */ -library SafeERC20 { - using Address for address; - - function safeTransfer( - IERC20 token, - address to, - uint256 value - ) internal { - _callOptionalReturn(token, abi.encodeWithSelector(token.transfer.selector, to, value)); - } - - function safeTransferFrom( - IERC20 token, - address from, - address to, - uint256 value - ) internal { - _callOptionalReturn(token, abi.encodeWithSelector(token.transferFrom.selector, from, to, value)); - } - - /** - * @dev Deprecated. This function has issues similar to the ones found in - * {IERC20-approve}, and its usage is discouraged. - * - * Whenever possible, use {safeIncreaseAllowance} and - * {safeDecreaseAllowance} instead. - */ - function safeApprove( - IERC20 token, - address spender, - uint256 value - ) internal { - // safeApprove should only be called when setting an initial allowance, - // or when resetting it to zero. To increase and decrease it, use - // 'safeIncreaseAllowance' and 'safeDecreaseAllowance' - require( - (value == 0) || (token.allowance(address(this), spender) == 0), - "SafeERC20: approve from non-zero to non-zero allowance" - ); - _callOptionalReturn(token, abi.encodeWithSelector(token.approve.selector, spender, value)); - } - - function safeIncreaseAllowance( - IERC20 token, - address spender, - uint256 value - ) internal { - uint256 newAllowance = token.allowance(address(this), spender) + value; - _callOptionalReturn(token, abi.encodeWithSelector(token.approve.selector, spender, newAllowance)); - } - - function safeDecreaseAllowance( - IERC20 token, - address spender, - uint256 value - ) internal { - unchecked { - uint256 oldAllowance = token.allowance(address(this), spender); - require(oldAllowance >= value, "SafeERC20: decreased allowance below zero"); - uint256 newAllowance = oldAllowance - value; - _callOptionalReturn(token, abi.encodeWithSelector(token.approve.selector, spender, newAllowance)); - } - } - - function safePermit( - IERC20Permit token, - address owner, - address spender, - uint256 value, - uint256 deadline, - uint8 v, - bytes32 r, - bytes32 s - ) internal { - uint256 nonceBefore = token.nonces(owner); - token.permit(owner, spender, value, deadline, v, r, s); - uint256 nonceAfter = token.nonces(owner); - require(nonceAfter == nonceBefore + 1, "SafeERC20: permit did not succeed"); - } - - /** - * @dev Imitates a Solidity high-level call (i.e. a regular function call to a contract), relaxing the requirement - * on the return value: the return value is optional (but if data is returned, it must not be false). - * @param token The token targeted by the call. - * @param data The call data (encoded using abi.encode or one of its variants). - */ - function _callOptionalReturn(IERC20 token, bytes memory data) private { - // We need to perform a low level call here, to bypass Solidity's return data size checking mechanism, since - // we're implementing it ourselves. We use {Address.functionCall} to perform this call, which verifies that - // the target address contains contract code and also asserts for success in the low-level call. - - bytes memory returndata = address(token).functionCall(data, "SafeERC20: low-level call failed"); - if (returndata.length > 0) { - // Return data is optional - require(abi.decode(returndata, (bool)), "SafeERC20: ERC20 operation did not succeed"); - } - } -} - - - - - - - - - - - - - - -/** - * @dev Provides information about the current execution context, including the - * sender of the transaction and its data. While these are generally available - * via msg.sender and msg.data, they should not be accessed in such a direct - * manner, since when dealing with meta-transactions the account sending and - * paying for execution may not be the actual sender (as far as an application - * is concerned). - * - * This contract is only required for intermediate, library-like contracts. - */ -abstract contract Context { - function _msgSender() internal view virtual returns (address) { - return msg.sender; - } - - function _msgData() internal view virtual returns (bytes calldata) { - return msg.data; - } -} - - -/** - * @dev Contract module which provides a basic access control mechanism, where - * there is an account (an owner) that can be granted exclusive access to - * specific functions. - * - * By default, the owner account will be the one that deploys the contract. This - * can later be changed with {transferOwnership}. - * - * This module is used through inheritance. It will make available the modifier - * `onlyOwner`, which can be applied to your functions to restrict their use to - * the owner. - */ -abstract contract Ownable is Context { - address private _owner; - - event OwnershipTransferred(address indexed previousOwner, address indexed newOwner); - - /** - * @dev Initializes the contract setting the deployer as the initial owner. - */ - constructor() { - _transferOwnership(_msgSender()); - } - - /** - * @dev Throws if called by any account other than the owner. - */ - modifier onlyOwner() { - _checkOwner(); - _; - } - - /** - * @dev Returns the address of the current owner. - */ - function owner() public view virtual returns (address) { - return _owner; - } - - /** - * @dev Throws if the sender is not the owner. - */ - function _checkOwner() internal view virtual { - require(owner() == _msgSender(), "Ownable: caller is not the owner"); - } - - /** - * @dev Leaves the contract without owner. It will not be possible to call - * `onlyOwner` functions anymore. Can only be called by the current owner. - * - * NOTE: Renouncing ownership will leave the contract without an owner, - * thereby removing any functionality that is only available to the owner. - */ - function renounceOwnership() public virtual onlyOwner { - _transferOwnership(address(0)); - } - - /** - * @dev Transfers ownership of the contract to a new account (`newOwner`). - * Can only be called by the current owner. - */ - function transferOwnership(address newOwner) public virtual onlyOwner { - require(newOwner != address(0), "Ownable: new owner is the zero address"); - _transferOwnership(newOwner); - } - - /** - * @dev Transfers ownership of the contract to a new account (`newOwner`). - * Internal function without access restriction. - */ - function _transferOwnership(address newOwner) internal virtual { - address oldOwner = _owner; - _owner = newOwner; - emit OwnershipTransferred(oldOwner, newOwner); - } -} - - -contract Operator is Ownable { - address public operator; - uint256 constant baseRate = 10000; - - modifier onlyOperator { - require(msg.sender == owner() || msg.sender == operator, "no permission"); - _; - } - - function setOperator(address operator_) external onlyOwner { - operator = operator_; - } - - - function getCurrTime() external view returns(uint256) { - return block.timestamp; - } - - function getBlockNum() external view returns(uint256) { - return block.number; - } - -} - - - - - -/** - * @dev Library for managing - * https://en.wikipedia.org/wiki/Set_(abstract_data_type)[sets] of primitive - * types. - * - * Sets have the following properties: - * - * - Elements are added, removed, and checked for existence in constant time - * (O(1)). - * - Elements are enumerated in O(n). No guarantees are made on the ordering. - * - * ``` - * contract Example { - * // Add the library methods - * using EnumerableSet for EnumerableSet.AddressSet; - * - * // Declare a set state variable - * EnumerableSet.AddressSet private mySet; - * } - * ``` - * - * As of v3.3.0, sets of type `bytes32` (`Bytes32Set`), `address` (`AddressSet`) - * and `uint256` (`UintSet`) are supported. - * - * [WARNING] - * ==== - * Trying to delete such a structure from storage will likely result in data corruption, rendering the structure unusable. - * See https://github.com/ethereum/solidity/pull/11843[ethereum/solidity#11843] for more info. - * - * In order to clean an EnumerableSet, you can either remove all elements one by one or create a fresh instance using an array of EnumerableSet. - * ==== - */ - -library EnumerableSet { - // To implement this library for multiple types with as little code - // repetition as possible, we write it in terms of a generic Set type with - // bytes32 values. - // The Set implementation uses private functions, and user-facing - // implementations (such as AddressSet) are just wrappers around the - // underlying Set. - // This means that we can only create new EnumerableSets for types that fit - // in bytes32. - - struct Set { - // Storage of set values - bytes32[] _values; - // Position of the value in the `values` array, plus 1 because index 0 - // means a value is not in the set. - mapping(bytes32 => uint256) _indexes; - } - - /** - * @dev Add a value to a set. O(1). - * - * Returns true if the value was added to the set, that is if it was not - * already present. - */ - function _add(Set storage set, bytes32 value) private returns (bool) { - if (!_contains(set, value)) { - set._values.push(value); - // The value is stored at length-1, but we add 1 to all indexes - // and use 0 as a sentinel value - set._indexes[value] = set._values.length; - return true; - } else { - return false; - } - } - - /** - * @dev Removes a value from a set. O(1). - * - * Returns true if the value was removed from the set, that is if it was - * present. - */ - function _remove(Set storage set, bytes32 value) private returns (bool) { - // We read and store the value's index to prevent multiple reads from the same storage slot - uint256 valueIndex = set._indexes[value]; - - if (valueIndex != 0) { - // Equivalent to contains(set, value) - // To delete an element from the _values array in O(1), we swap the element to delete with the last one in - // the array, and then remove the last element (sometimes called as 'swap and pop'). - // This modifies the order of the array, as noted in {at}. - - uint256 toDeleteIndex = valueIndex - 1; - uint256 lastIndex = set._values.length - 1; - - if (lastIndex != toDeleteIndex) { - bytes32 lastValue = set._values[lastIndex]; - - // Move the last value to the index where the value to delete is - set._values[toDeleteIndex] = lastValue; - // Update the index for the moved value - set._indexes[lastValue] = valueIndex; // Replace lastValue's index to valueIndex - } - - // Delete the slot where the moved value was stored - set._values.pop(); - - // Delete the index for the deleted slot - delete set._indexes[value]; - - return true; - } else { - return false; - } - } - - /** - * @dev Returns true if the value is in the set. O(1). - */ - function _contains(Set storage set, bytes32 value) private view returns (bool) { - return set._indexes[value] != 0; - } - - /** - * @dev Returns the number of values on the set. O(1). - */ - function _length(Set storage set) private view returns (uint256) { - return set._values.length; - } - - /** - * @dev Returns the value stored at position `index` in the set. O(1). - * - * Note that there are no guarantees on the ordering of values inside the - * array, and it may change when more values are added or removed. - * - * Requirements: - * - * - `index` must be strictly less than {length}. - */ - function _at(Set storage set, uint256 index) private view returns (bytes32) { - return set._values[index]; - } - - /** - * @dev Return the entire set in an array - * - * WARNING: This operation will copy the entire storage to memory, which can be quite expensive. This is designed - * to mostly be used by view accessors that are queried without any gas fees. Developers should keep in mind that - * this function has an unbounded cost, and using it as part of a state-changing function may render the function - * uncallable if the set grows to a point where copying to memory consumes too much gas to fit in a block. - */ - function _values(Set storage set) private view returns (bytes32[] memory) { - return set._values; - } - - // Bytes32Set - - struct Bytes32Set { - Set _inner; - } - - /** - * @dev Add a value to a set. O(1). - * - * Returns true if the value was added to the set, that is if it was not - * already present. - */ - function add(Bytes32Set storage set, bytes32 value) internal returns (bool) { - return _add(set._inner, value); - } - - /** - * @dev Removes a value from a set. O(1). - * - * Returns true if the value was removed from the set, that is if it was - * present. - */ - function remove(Bytes32Set storage set, bytes32 value) internal returns (bool) { - return _remove(set._inner, value); - } - - /** - * @dev Returns true if the value is in the set. O(1). - */ - function contains(Bytes32Set storage set, bytes32 value) internal view returns (bool) { - return _contains(set._inner, value); - } - - /** - * @dev Returns the number of values in the set. O(1). - */ - function length(Bytes32Set storage set) internal view returns (uint256) { - return _length(set._inner); - } - - /** - * @dev Returns the value stored at position `index` in the set. O(1). - * - * Note that there are no guarantees on the ordering of values inside the - * array, and it may change when more values are added or removed. - * - * Requirements: - * - * - `index` must be strictly less than {length}. - */ - function at(Bytes32Set storage set, uint256 index) internal view returns (bytes32) { - return _at(set._inner, index); - } - - /** - * @dev Return the entire set in an array - * - * WARNING: This operation will copy the entire storage to memory, which can be quite expensive. This is designed - * to mostly be used by view accessors that are queried without any gas fees. Developers should keep in mind that - * this function has an unbounded cost, and using it as part of a state-changing function may render the function - * uncallable if the set grows to a point where copying to memory consumes too much gas to fit in a block. - */ - function values(Bytes32Set storage set) internal view returns (bytes32[] memory) { - return _values(set._inner); - } - - // AddressSet - - struct AddressSet { - Set _inner; - } - - /** - * @dev Add a value to a set. O(1). - * - * Returns true if the value was added to the set, that is if it was not - * already present. - */ - function add(AddressSet storage set, address value) internal returns (bool) { - return _add(set._inner, bytes32(uint256(uint160(value)))); - } - - /** - * @dev Removes a value from a set. O(1). - * - * Returns true if the value was removed from the set, that is if it was - * present. - */ - function remove(AddressSet storage set, address value) internal returns (bool) { - return _remove(set._inner, bytes32(uint256(uint160(value)))); - } - - /** - * @dev Returns true if the value is in the set. O(1). - */ - function contains(AddressSet storage set, address value) internal view returns (bool) { - return _contains(set._inner, bytes32(uint256(uint160(value)))); - } - - /** - * @dev Returns the number of values in the set. O(1). - */ - function length(AddressSet storage set) internal view returns (uint256) { - return _length(set._inner); - } - - /** - * @dev Returns the value stored at position `index` in the set. O(1). - * - * Note that there are no guarantees on the ordering of values inside the - * array, and it may change when more values are added or removed. - * - * Requirements: - * - * - `index` must be strictly less than {length}. - */ - function at(AddressSet storage set, uint256 index) internal view returns (address) { - return address(uint160(uint256(_at(set._inner, index)))); - } - - /** - * @dev Return the entire set in an array - * - * WARNING: This operation will copy the entire storage to memory, which can be quite expensive. This is designed - * to mostly be used by view accessors that are queried without any gas fees. Developers should keep in mind that - * this function has an unbounded cost, and using it as part of a state-changing function may render the function - * uncallable if the set grows to a point where copying to memory consumes too much gas to fit in a block. - */ - function values(AddressSet storage set) internal view returns (address[] memory) { - bytes32[] memory store = _values(set._inner); - address[] memory result; - - /// @solidity memory-safe-assembly - assembly { - result := store - } - - return result; - } - - // UintSet - - struct UintSet { - Set _inner; - } - - /** - * @dev Add a value to a set. O(1). - * - * Returns true if the value was added to the set, that is if it was not - * already present. - */ - function add(UintSet storage set, uint256 value) internal returns (bool) { - return _add(set._inner, bytes32(value)); - } - - /** - * @dev Removes a value from a set. O(1). - * - * Returns true if the value was removed from the set, that is if it was - * present. - */ - function remove(UintSet storage set, uint256 value) internal returns (bool) { - return _remove(set._inner, bytes32(value)); - } - - /** - * @dev Returns true if the value is in the set. O(1). - */ - function contains(UintSet storage set, uint256 value) internal view returns (bool) { - return _contains(set._inner, bytes32(value)); - } - - /** - * @dev Returns the number of values on the set. O(1). - */ - function length(UintSet storage set) internal view returns (uint256) { - return _length(set._inner); - } - - /** - * @dev Returns the value stored at position `index` in the set. O(1). - * - * Note that there are no guarantees on the ordering of values inside the - * array, and it may change when more values are added or removed. - * - * Requirements: - * - * - `index` must be strictly less than {length}. - */ - function at(UintSet storage set, uint256 index) internal view returns (uint256) { - return uint256(_at(set._inner, index)); - } - - /** - * @dev Return the entire set in an array - * - * WARNING: This operation will copy the entire storage to memory, which can be quite expensive. This is designed - * to mostly be used by view accessors that are queried without any gas fees. Developers should keep in mind that - * this function has an unbounded cost, and using it as part of a state-changing function may render the function - * uncallable if the set grows to a point where copying to memory consumes too much gas to fit in a block. - */ - function values(UintSet storage set) internal view returns (uint256[] memory) { - bytes32[] memory store = _values(set._inner); - uint256[] memory result; - - /// @solidity memory-safe-assembly - assembly { - result := store - } - - return result; - } -} - - -contract ActivityPool is Operator { - using SafeMath for uint256; - using SafeERC20 for IERC20; - using EnumerableSet for EnumerableSet.AddressSet; - using EnumerableSet for EnumerableSet.UintSet; - - event AddNewAct(uint256 id); - event Bet(address user, uint256 pID, uint256 bType, uint256 amount, uint256 time); - event SetPrize(uint256 pID, uint256 bType); - event Claim(address user, uint256 pID, uint256 bType, uint256 amount); - event RemovePeriodAct(uint256 pID); - - uint256 public constant muti = 1e18; - uint256 public periodID; - uint256 public betID; - - struct UserInfo { - address user; - uint256 pID; - uint256 amount; - uint256 betTime; - uint256 bType; - uint256 claimAmount; - } - - struct ActInfo { - string name; - string aName; - string bName; - address rewardToken; - uint256 startTime; - uint256 endTime; - uint256 minAmount; - uint256 maxAmount; - uint256 aAmount; - uint256 bAmount; - uint256 winType; - bool isBet; - } - - struct TimeInfo { - uint256 time; - uint256 aAmount; - uint256 bAmount; - } - - struct BestInfo { - address aUser; - address bUser; - uint256 aBet; - uint256 bBet; - } - - mapping(uint256 => BestInfo) bestInfo; - mapping(uint256 => uint256) public timeID; - mapping(uint256 => mapping(uint256 => TimeInfo)) public timeInfo; - mapping(address => mapping(uint256 => uint256)) public userBet; - mapping(uint256 => UserInfo) public betInfo; - mapping(uint256 => uint256) public perAmount; - mapping(uint256 => ActInfo) public actInfo; - mapping(uint256 => mapping(uint256 => string)) public descripName; - - mapping(address => EnumerableSet.UintSet) userPid; - mapping(uint256 => EnumerableSet.AddressSet) aUsers; - mapping(uint256 => EnumerableSet.AddressSet) bUsers; - EnumerableSet.UintSet activePeriod; - EnumerableSet.UintSet removePeriod; - - function addNewAct( - string memory name, - string memory aName, - string memory bName, - address token, - uint256 startTime, - uint256 endTime, - uint256 minAmount, - uint256 maxAmount - ) external onlyOperator { - - checkAdd(msg.sender, startTime, endTime, minAmount, maxAmount); - uint256 id = ++periodID; - actInfo[id].name = name; - actInfo[id].aName = aName; - actInfo[id].bName = bName; - actInfo[id].startTime = startTime; - actInfo[id].endTime = endTime; - actInfo[id].minAmount = minAmount; - actInfo[id].maxAmount = maxAmount; - actInfo[id].rewardToken = token; - descripName[id][1] = aName; - descripName[id][2] = bName; - activePeriod.add(id); - - emit AddNewAct(id); - } - - - function removePeriodAct(uint256 pID) external onlyOperator { - checkRemove(pID); - - activePeriod.remove(pID); - removePeriod.add(pID); - - emit RemovePeriodAct(pID); - } - - - function bet(uint256 pID, uint256 bType, uint256 amount) external payable { - checkBet(msg.sender, pID, bType, amount); - if(actInfo[pID].rewardToken == address(0)) { - require(msg.value == amount, "value err"); - } else { - require(msg.value == 0, "value amount err"); - } - - if(bType == 1) { - if(amount > bestInfo[pID].aBet) { - bestInfo[pID].aUser = msg.sender; - bestInfo[pID].aBet = amount; - } - } else { - if(amount > bestInfo[pID].bBet) { - bestInfo[pID].bUser = msg.sender; - bestInfo[pID].bBet = amount; - } - } - - userPid[msg.sender].add(pID); - uint256 id = ++betID; - userBet[msg.sender][pID] = id; - - if(bType == 1) { - aUsers[pID].add(msg.sender); - actInfo[pID].aAmount = actInfo[pID].aAmount.add(amount); - } else { - bUsers[pID].add(msg.sender); - actInfo[pID].bAmount = actInfo[pID].bAmount.add(amount); - } - - actInfo[pID].isBet = true; - betInfo[id].user = msg.sender; - betInfo[id].pID = pID; - betInfo[id].amount = amount; - betInfo[id].betTime = block.timestamp; - betInfo[id].bType = bType; - - uint256 tID = ++timeID[pID]; - timeInfo[pID][tID].time = block.timestamp; - timeInfo[pID][tID].aAmount = actInfo[pID].aAmount; - timeInfo[pID][tID].bAmount = actInfo[pID].bAmount; - - if(actInfo[pID].rewardToken != address(0)) { - IERC20(actInfo[pID].rewardToken).safeTransferFrom(msg.sender, address(this), amount); - } - emit Bet(msg.sender, pID, bType, amount, betInfo[id].betTime); - } - - function setPrize(uint256 pID, uint256 bType) external onlyOperator { - checkSetPrize(msg.sender, pID, bType); - - if(block.timestamp <= actInfo[pID].startTime) { - actInfo[pID].startTime = block.timestamp; - - } - actInfo[pID].endTime = block.timestamp; - - actInfo[pID].winType = bType; - perAmount[pID] = getPerAmount(pID, bType); - - emit SetPrize(pID, bType); - } - - function recive() public payable {} - - function claim(uint256 pID) external { - uint256 amount = checkClaim(msg.sender, pID); - - uint256 id = userBet[msg.sender][pID]; - betInfo[id].claimAmount = amount; - if(actInfo[pID].rewardToken != address(0)) { - IERC20(actInfo[pID].rewardToken).safeTransfer(msg.sender, amount); - } else { - payable(msg.sender).transfer(amount); - } - - emit Claim(msg.sender, pID, betInfo[id].bType, amount); - } - - function checkClaim(address user, uint256 pID) public view returns(uint256 amount) { - require(userPid[user].contains(pID), "not bet"); - uint256 id = userBet[user][pID]; - require(betInfo[id].user == user, "not user"); - require(actInfo[pID].winType != 0, "not prize"); - require(betInfo[id].claimAmount == 0, "has claim"); - - if(actInfo[pID].winType != 3) { - require(actInfo[pID].winType == betInfo[id].bType, "not right"); - amount = perAmount[pID].mul(betInfo[id].amount).div(muti); - require(amount > 0, "no amount"); - } else { - amount = betInfo[id].amount; - } - - return amount; - } - - function getActualRate( - address user, - uint256 pID, - uint256 bType, - uint256 amount - ) external view returns(uint256, uint256, bool) { - if(bType < 1 || bType > 2 || !activePeriod.contains(pID)) { - return (0, 0, false); - } else if(userBet[user][pID] != 0 || actInfo[pID].winType != 0 || amount == 0) { - (uint256 ra, uint256 rb) = getRate(pID, timeID[pID]); - return (ra, rb, false); - } else { - (uint256 aAmount, uint256 bAmount) = (actInfo[pID].aAmount, actInfo[pID].bAmount); - if(bType == 1) { - aAmount = aAmount.add(amount); - } else { - bAmount = bAmount.add(amount); - } - - uint256 total = aAmount.add(bAmount); - if(bAmount == 0 && aAmount != 0) { - return (muti, 0, true); - } - if(bAmount != 0 && aAmount == 0) { - return (0, muti, true); - } - return (total.mul(muti).div(aAmount), total.mul(muti).div(bAmount), true); - } - } - - function getRate(uint256 pID, uint256 tID) public view returns(uint256, uint256) { - (uint256 aAmount, uint256 bAmount) = (timeInfo[pID][tID].aAmount, timeInfo[pID][tID].bAmount); - uint256 total = aAmount.add(bAmount); - if(total == 0) { - return (0, 0); - } - if(bAmount == 0 && aAmount != 0) { - return (muti, 0); - } - if(bAmount != 0 && aAmount == 0) { - return (0, muti); - } - return (total.mul(muti).div(aAmount), total.mul(muti).div(bAmount)); - } - - function getBestInfo(uint256 pID) - external - view - returns(address aUser, address bUser, uint256 aBet, uint256 bBet, uint256 aReward, uint256 bReward) - { - aUser = bestInfo[pID].aUser; - bUser = bestInfo[pID].bUser; - aBet = bestInfo[pID].aBet; - bBet = bestInfo[pID].bBet; - aReward = getPerAmount(pID, 1).mul(aBet).div(muti); - bReward = getPerAmount(pID, 2).mul(bBet).div(muti); - } - - function getPerAmount(uint256 pID, uint256 bType) public view returns(uint256) { - uint256 total = actInfo[pID].aAmount.add(actInfo[pID].bAmount); - if(total == 0) { - return 0; - } - - if(actInfo[pID].winType == 3) { - return muti; - } - - if(bType == 1) { - if(actInfo[pID].aAmount == 0 || actInfo[pID].winType == 2) { - return 0; - } - return total.mul(muti).div(actInfo[pID].aAmount); - } - - if(bType == 2) { - if(actInfo[pID].bAmount == 0 || actInfo[pID].winType == 1) { - return 0; - } - return total.mul(muti).div(actInfo[pID].bAmount); - } - - return 0; - - } - - function checkSetPrize(address user, uint256 pID, uint256 bType) public view returns(bool) { - require(user == owner() || user == operator, "no permission"); - require(bType > 0 && bType <= 3, "type err"); - require(activePeriod.contains(pID), "not active"); - require(actInfo[pID].winType == 0, "has set"); - - return true; - } - - function checkBet( - address user, - uint256 pID, - uint256 bType, - uint256 amount - ) public view returns(bool) { - require(activePeriod.contains(pID), "not active"); - require(actInfo[pID].startTime <= block.timestamp, "not start"); - require(actInfo[pID].endTime > block.timestamp, "has end"); - require(!userPid[user].contains(pID), "has bet"); - require(bType > 0 && bType < 3, "type err"); - require(amount >= actInfo[pID].minAmount && amount <= actInfo[pID].maxAmount, "amount err"); - if(actInfo[pID].rewardToken != address(0)) { - require(IERC20(actInfo[pID].rewardToken).allowance(user, address(this)) >= amount, "not approve enough"); - require(IERC20(actInfo[pID].rewardToken).balanceOf(user) >= amount, "not enough"); - } else { - require(user.balance >= amount, "main token err"); - } - - return true; - } - - - function checkRemove(uint256 pID) public view returns(bool) { - require(activePeriod.contains(pID), "not in"); - require(!actInfo[pID].isBet, "has bet"); - - return true; - } - - function checkAdd( - address user, - uint256 startTime, - uint256 endTime, - uint256 minAmount, - uint256 maxAmount - ) public view returns(bool) { - require(user == owner() || user == operator, "no permission"); - require(startTime > block.timestamp, "startTime err"); - require(endTime > startTime, "endTime err"); - require(minAmount > 0 && maxAmount > minAmount, "amount err"); - - return true; - } - - function getStatus(uint256 pID) external view returns(uint256) { - if(!removePeriod.contains(pID) && !activePeriod.contains(pID)) { - return 5; - } else if(removePeriod.contains(pID)) { - return 6; - } else if(block.timestamp < actInfo[pID].startTime) { - return 1; - } else if ( - actInfo[pID].startTime <= block.timestamp && - actInfo[pID].endTime > block.timestamp - ) { - return 2; - } else if (actInfo[pID].endTime <= block.timestamp && actInfo[pID].winType == 0){ - return 3; - } else if(actInfo[pID].winType != 0) { - return 4; - } - return 0; - } - - function getUserPidNum(address user) external view returns(uint256) { - return userPid[user].length(); - } - - function getUserPid(address user, uint256 index) external view returns(uint256) { - return userPid[user].at(index); - } - - function getAUsersNum(uint256 pID) external view returns(uint256) { - return aUsers[pID].length(); - } - - function getAUsers(uint256 pID, uint256 index) external view returns(address) { - return aUsers[pID].at(index); - } - - function getBUsersNum(uint256 pID) external view returns(uint256) { - return bUsers[pID].length(); - } - - function getBUsers(uint256 pID, uint256 index) external view returns(address) { - return bUsers[pID].at(index); - } - - function getActivePeriodNum() external view returns(uint256) { - return activePeriod.length(); - } - - function getActivePeriod(uint256 index) external view returns(uint256) { - return activePeriod.at(index); - } - - function getRemovePeriodNum() external view returns(uint256) { - return removePeriod.length(); - } - - function getRemovePeriod(uint256 index) external view returns(uint256) { - return removePeriod.at(index); - } -} \ No newline at end of file diff --git a/app/api/uploads/ActivityPool-1729821496223-688339861.sol b/app/api/uploads/ActivityPool-1729821496223-688339861.sol deleted file mode 100644 index daf3372..0000000 --- a/app/api/uploads/ActivityPool-1729821496223-688339861.sol +++ /dev/null @@ -1,1648 +0,0 @@ -// SPDX-License-Identifier: MIT -// OpenZeppelin Contracts (last updated v4.7.0) (utils/Address.sol) - -pragma solidity ^0.8.1; - -/** - * @dev Collection of functions related to the address type - */ -library Address { - /** - * @dev Returns true if `account` is a contract. - * - * [IMPORTANT] - * ==== - * It is unsafe to assume that an address for which this function returns - * false is an externally-owned account (EOA) and not a contract. - * - * Among others, `isContract` will return false for the following - * types of addresses: - * - * - an externally-owned account - * - a contract in construction - * - an address where a contract will be created - * - an address where a contract lived, but was destroyed - * ==== - * - * [IMPORTANT] - * ==== - * You shouldn't rely on `isContract` to protect against flash loan attacks! - * - * Preventing calls from contracts is highly discouraged. It breaks composability, breaks support for smart wallets - * like Gnosis Safe, and does not provide security since it can be circumvented by calling from a contract - * constructor. - * ==== - */ - function isContract(address account) internal view returns (bool) { - // This method relies on extcodesize/address.code.length, which returns 0 - // for contracts in construction, since the code is only stored at the end - // of the constructor execution. - - return account.code.length > 0; - } - - /** - * @dev Replacement for Solidity's `transfer`: sends `amount` wei to - * `recipient`, forwarding all available gas and reverting on errors. - * - * https://eips.ethereum.org/EIPS/eip-1884[EIP1884] increases the gas cost - * of certain opcodes, possibly making contracts go over the 2300 gas limit - * imposed by `transfer`, making them unable to receive funds via - * `transfer`. {sendValue} removes this limitation. - * - * https://diligence.consensys.net/posts/2019/09/stop-using-soliditys-transfer-now/[Learn more]. - * - * IMPORTANT: because control is transferred to `recipient`, care must be - * taken to not create reentrancy vulnerabilities. Consider using - * {ReentrancyGuard} or the - * https://solidity.readthedocs.io/en/v0.5.11/security-considerations.html#use-the-checks-effects-interactions-pattern[checks-effects-interactions pattern]. - */ - function sendValue(address payable recipient, uint256 amount) internal { - require(address(this).balance >= amount, "Address: insufficient balance"); - - (bool success, ) = recipient.call{value: amount}(""); - require(success, "Address: unable to send value, recipient may have reverted"); - } - - /** - * @dev Performs a Solidity function call using a low level `call`. A - * plain `call` is an unsafe replacement for a function call: use this - * function instead. - * - * If `target` reverts with a revert reason, it is bubbled up by this - * function (like regular Solidity function calls). - * - * Returns the raw returned data. To convert to the expected return value, - * use https://solidity.readthedocs.io/en/latest/units-and-global-variables.html?highlight=abi.decode#abi-encoding-and-decoding-functions[`abi.decode`]. - * - * Requirements: - * - * - `target` must be a contract. - * - calling `target` with `data` must not revert. - * - * _Available since v3.1._ - */ - function functionCall(address target, bytes memory data) internal returns (bytes memory) { - return functionCallWithValue(target, data, 0, "Address: low-level call failed"); - } - - /** - * @dev Same as {xref-Address-functionCall-address-bytes-}[`functionCall`], but with - * `errorMessage` as a fallback revert reason when `target` reverts. - * - * _Available since v3.1._ - */ - function functionCall( - address target, - bytes memory data, - string memory errorMessage - ) internal returns (bytes memory) { - return functionCallWithValue(target, data, 0, errorMessage); - } - - /** - * @dev Same as {xref-Address-functionCall-address-bytes-}[`functionCall`], - * but also transferring `value` wei to `target`. - * - * Requirements: - * - * - the calling contract must have an ETH balance of at least `value`. - * - the called Solidity function must be `payable`. - * - * _Available since v3.1._ - */ - function functionCallWithValue( - address target, - bytes memory data, - uint256 value - ) internal returns (bytes memory) { - return functionCallWithValue(target, data, value, "Address: low-level call with value failed"); - } - - /** - * @dev Same as {xref-Address-functionCallWithValue-address-bytes-uint256-}[`functionCallWithValue`], but - * with `errorMessage` as a fallback revert reason when `target` reverts. - * - * _Available since v3.1._ - */ - function functionCallWithValue( - address target, - bytes memory data, - uint256 value, - string memory errorMessage - ) internal returns (bytes memory) { - require(address(this).balance >= value, "Address: insufficient balance for call"); - (bool success, bytes memory returndata) = target.call{value: value}(data); - return verifyCallResultFromTarget(target, success, returndata, errorMessage); - } - - /** - * @dev Same as {xref-Address-functionCall-address-bytes-}[`functionCall`], - * but performing a static call. - * - * _Available since v3.3._ - */ - function functionStaticCall(address target, bytes memory data) internal view returns (bytes memory) { - return functionStaticCall(target, data, "Address: low-level static call failed"); - } - - /** - * @dev Same as {xref-Address-functionCall-address-bytes-string-}[`functionCall`], - * but performing a static call. - * - * _Available since v3.3._ - */ - function functionStaticCall( - address target, - bytes memory data, - string memory errorMessage - ) internal view returns (bytes memory) { - (bool success, bytes memory returndata) = target.staticcall(data); - return verifyCallResultFromTarget(target, success, returndata, errorMessage); - } - - /** - * @dev Same as {xref-Address-functionCall-address-bytes-}[`functionCall`], - * but performing a delegate call. - * - * _Available since v3.4._ - */ - function functionDelegateCall(address target, bytes memory data) internal returns (bytes memory) { - return functionDelegateCall(target, data, "Address: low-level delegate call failed"); - } - - /** - * @dev Same as {xref-Address-functionCall-address-bytes-string-}[`functionCall`], - * but performing a delegate call. - * - * _Available since v3.4._ - */ - function functionDelegateCall( - address target, - bytes memory data, - string memory errorMessage - ) internal returns (bytes memory) { - (bool success, bytes memory returndata) = target.delegatecall(data); - return verifyCallResultFromTarget(target, success, returndata, errorMessage); - } - - /** - * @dev Tool to verify that a low level call to smart-contract was successful, and revert (either by bubbling - * the revert reason or using the provided one) in case of unsuccessful call or if target was not a contract. - * - * _Available since v4.8._ - */ - function verifyCallResultFromTarget( - address target, - bool success, - bytes memory returndata, - string memory errorMessage - ) internal view returns (bytes memory) { - if (success) { - if (returndata.length == 0) { - // only check isContract if the call was successful and the return data is empty - // otherwise we already know that it was a contract - require(isContract(target), "Address: call to non-contract"); - } - return returndata; - } else { - _revert(returndata, errorMessage); - } - } - - /** - * @dev Tool to verify that a low level call was successful, and revert if it wasn't, either by bubbling the - * revert reason or using the provided one. - * - * _Available since v4.3._ - */ - function verifyCallResult( - bool success, - bytes memory returndata, - string memory errorMessage - ) internal pure returns (bytes memory) { - if (success) { - return returndata; - } else { - _revert(returndata, errorMessage); - } - } - - function _revert(bytes memory returndata, string memory errorMessage) private pure { - // Look for revert reason and bubble it up if present - if (returndata.length > 0) { - // The easiest way to bubble the revert reason is using memory via assembly - /// @solidity memory-safe-assembly - assembly { - let returndata_size := mload(returndata) - revert(add(32, returndata), returndata_size) - } - } else { - revert(errorMessage); - } - } -} - -// OpenZeppelin Contracts (last updated v4.6.0) (token/ERC20/IERC20.sol) - - - -/** - * @dev Interface of the ERC20 standard as defined in the EIP. - */ -interface IERC20 { - /** - * @dev Emitted when `value` tokens are moved from one account (`from`) to - * another (`to`). - * - * Note that `value` may be zero. - */ - event Transfer(address indexed from, address indexed to, uint256 value); - - /** - * @dev Emitted when the allowance of a `spender` for an `owner` is set by - * a call to {approve}. `value` is the new allowance. - */ - event Approval(address indexed owner, address indexed spender, uint256 value); - - /** - * @dev Returns the amount of tokens in existence. - */ - function totalSupply() external view returns (uint256); - - /** - * @dev Returns the amount of tokens owned by `account`. - */ - function balanceOf(address account) external view returns (uint256); - - /** - * @dev Moves `amount` tokens from the caller's account to `to`. - * - * Returns a boolean value indicating whether the operation succeeded. - * - * Emits a {Transfer} event. - */ - function transfer(address to, uint256 amount) external returns (bool); - - /** - * @dev Returns the remaining number of tokens that `spender` will be - * allowed to spend on behalf of `owner` through {transferFrom}. This is - * zero by default. - * - * This value changes when {approve} or {transferFrom} are called. - */ - function allowance(address owner, address spender) external view returns (uint256); - - /** - * @dev Sets `amount` as the allowance of `spender` over the caller's tokens. - * - * Returns a boolean value indicating whether the operation succeeded. - * - * IMPORTANT: Beware that changing an allowance with this method brings the risk - * that someone may use both the old and the new allowance by unfortunate - * transaction ordering. One possible solution to mitigate this race - * condition is to first reduce the spender's allowance to 0 and set the - * desired value afterwards: - * https://github.com/ethereum/EIPs/issues/20#issuecomment-263524729 - * - * Emits an {Approval} event. - */ - function approve(address spender, uint256 amount) external returns (bool); - - /** - * @dev Moves `amount` tokens from `from` to `to` using the - * allowance mechanism. `amount` is then deducted from the caller's - * allowance. - * - * Returns a boolean value indicating whether the operation succeeded. - * - * Emits a {Transfer} event. - */ - function transferFrom( - address from, - address to, - uint256 amount - ) external returns (bool); - - - function mint(address account_, uint256 amount_) external; - - function burn(uint256 amount) external; - -} - - - - - - - - - - - -/** - * @dev Wrappers over Solidity's arithmetic operations with added overflow - * checks. - * - * Arithmetic operations in Solidity wrap on overflow. This can easily result - * in bugs, because programmers usually assume that an overflow raises an - * error, which is the standard behavior in high level programming languages. - * `SafeMath` restores this intuition by reverting the transaction when an - * operation overflows. - * - * Using this library instead of the unchecked operations eliminates an entire - * class of bugs, so it's recommended to use it always. - */ -library SafeMath { - /** - * @dev Returns the addition of two unsigned integers, reverting on - * overflow. - * - * Counterpart to Solidity's `+` operator. - * - * Requirements: - * - * - Addition cannot overflow. - */ - function add(uint256 a, uint256 b) internal pure returns (uint256) { - uint256 c = a + b; - require(c >= a, "SafeMath: addition overflow"); - - return c; - } - - /** - * @dev Returns the subtraction of two unsigned integers, reverting on - * overflow (when the result is negative). - * - * Counterpart to Solidity's `-` operator. - * - * Requirements: - * - * - Subtraction cannot overflow. - */ - function sub(uint256 a, uint256 b) internal pure returns (uint256) { - return sub(a, b, "SafeMath: subtraction overflow"); - } - - /** - * @dev Returns the subtraction of two unsigned integers, reverting with custom message on - * overflow (when the result is negative). - * - * Counterpart to Solidity's `-` operator. - * - * Requirements: - * - * - Subtraction cannot overflow. - */ - function sub( - uint256 a, - uint256 b, - string memory errorMessage - ) internal pure returns (uint256) { - require(b <= a, errorMessage); - uint256 c = a - b; - - return c; - } - - /** - * @dev Returns the multiplication of two unsigned integers, reverting on - * overflow. - * - * Counterpart to Solidity's `*` operator. - * - * Requirements: - * - * - Multiplication cannot overflow. - */ - function mul(uint256 a, uint256 b) internal pure returns (uint256) { - // Gas optimization: this is cheaper than requiring 'a' not being zero, but the - // benefit is lost if 'b' is also tested. - // See: https://github.com/OpenZeppelin/openzeppelin-contracts/pull/522 - if (a == 0) { - return 0; - } - - uint256 c = a * b; - require(c / a == b, "SafeMath: multiplication overflow"); - - return c; - } - - /** - * @dev Returns the integer division of two unsigned integers. Reverts on - * division by zero. The result is rounded towards zero. - * - * Counterpart to Solidity's `/` operator. Note: this function uses a - * `revert` opcode (which leaves remaining gas untouched) while Solidity - * uses an invalid opcode to revert (consuming all remaining gas). - * - * Requirements: - * - * - The divisor cannot be zero. - */ - function div(uint256 a, uint256 b) internal pure returns (uint256) { - return div(a, b, "SafeMath: division by zero"); - } - - /** - * @dev Returns the integer division of two unsigned integers. Reverts with custom message on - * division by zero. The result is rounded towards zero. - * - * Counterpart to Solidity's `/` operator. Note: this function uses a - * `revert` opcode (which leaves remaining gas untouched) while Solidity - * uses an invalid opcode to revert (consuming all remaining gas). - * - * Requirements: - * - * - The divisor cannot be zero. - */ - function div( - uint256 a, - uint256 b, - string memory errorMessage - ) internal pure returns (uint256) { - require(b > 0, errorMessage); - uint256 c = a / b; - // assert(a == b * c + a % b); // There is no case in which this doesn't hold - - return c; - } - - /** - * @dev Returns the remainder of dividing two unsigned integers. (unsigned integer modulo), - * Reverts when dividing by zero. - * - * Counterpart to Solidity's `%` operator. This function uses a `revert` - * opcode (which leaves remaining gas untouched) while Solidity uses an - * invalid opcode to revert (consuming all remaining gas). - * - * Requirements: - * - * - The divisor cannot be zero. - */ - function mod(uint256 a, uint256 b) internal pure returns (uint256) { - return mod(a, b, "SafeMath: modulo by zero"); - } - - /** - * @dev Returns the remainder of dividing two unsigned integers. (unsigned integer modulo), - * Reverts with custom message when dividing by zero. - * - * Counterpart to Solidity's `%` operator. This function uses a `revert` - * opcode (which leaves remaining gas untouched) while Solidity uses an - * invalid opcode to revert (consuming all remaining gas). - * - * Requirements: - * - * - The divisor cannot be zero. - */ - function mod( - uint256 a, - uint256 b, - string memory errorMessage - ) internal pure returns (uint256) { - require(b != 0, errorMessage); - return a % b; - } - - // babylonian method (https://en.wikipedia.org/wiki/Methods_of_computing_square_roots#Babylonian_method) - function sqrrt(uint256 a) internal pure returns (uint256 c) { - if (a > 3) { - c = a; - uint256 b = add(div(a, 2), 1); - while (b < c) { - c = b; - b = div(add(div(a, b), b), 2); - } - } else if (a != 0) { - c = 1; - } - } - - /* - * Expects percentage to be trailed by 00, - */ - function percentageAmount(uint256 total_, uint8 percentage_) internal pure returns (uint256 percentAmount_) { - return div(mul(total_, percentage_), 1000); - } - - /* - * Expects percentage to be trailed by 00, - */ - function substractPercentage(uint256 total_, uint8 percentageToSub_) internal pure returns (uint256 result_) { - return sub(total_, div(mul(total_, percentageToSub_), 1000)); - } - - function percentageOfTotal(uint256 part_, uint256 total_) internal pure returns (uint256 percent_) { - return div(mul(part_, 100), total_); - } - - /** - * Taken from Hypersonic https://github.com/M2629/HyperSonic/blob/main/Math.sol - * @dev Returns the average of two numbers. The result is rounded towards - * zero. - */ - function average(uint256 a, uint256 b) internal pure returns (uint256) { - // (a + b) / 2 can overflow, so we distribute - return (a / 2) + (b / 2) + (((a % 2) + (b % 2)) / 2); - } - - function quadraticPricing(uint256 payment_, uint256 multiplier_) internal pure returns (uint256) { - return sqrrt(mul(multiplier_, payment_)); - } - - function bondingCurve(uint256 supply_, uint256 multiplier_) internal pure returns (uint256) { - return mul(multiplier_, supply_); - } -} - -// OpenZeppelin Contracts (last updated v4.7.0) (token/ERC20/utils/SafeERC20.sol) - - - - - -// OpenZeppelin Contracts v4.4.1 (token/ERC20/extensions/draft-IERC20Permit.sol) - - - -/** - * @dev Interface of the ERC20 Permit extension allowing approvals to be made via signatures, as defined in - * https://eips.ethereum.org/EIPS/eip-2612[EIP-2612]. - * - * Adds the {permit} method, which can be used to change an account's ERC20 allowance (see {IERC20-allowance}) by - * presenting a message signed by the account. By not relying on {IERC20-approve}, the token holder account doesn't - * need to send a transaction, and thus is not required to hold Ether at all. - */ -interface IERC20Permit { - /** - * @dev Sets `value` as the allowance of `spender` over ``owner``'s tokens, - * given ``owner``'s signed approval. - * - * IMPORTANT: The same issues {IERC20-approve} has related to transaction - * ordering also apply here. - * - * Emits an {Approval} event. - * - * Requirements: - * - * - `spender` cannot be the zero address. - * - `deadline` must be a timestamp in the future. - * - `v`, `r` and `s` must be a valid `secp256k1` signature from `owner` - * over the EIP712-formatted function arguments. - * - the signature must use ``owner``'s current nonce (see {nonces}). - * - * For more information on the signature format, see the - * https://eips.ethereum.org/EIPS/eip-2612#specification[relevant EIP - * section]. - */ - function permit( - address owner, - address spender, - uint256 value, - uint256 deadline, - uint8 v, - bytes32 r, - bytes32 s - ) external; - - /** - * @dev Returns the current nonce for `owner`. This value must be - * included whenever a signature is generated for {permit}. - * - * Every successful call to {permit} increases ``owner``'s nonce by one. This - * prevents a signature from being used multiple times. - */ - function nonces(address owner) external view returns (uint256); - - /** - * @dev Returns the domain separator used in the encoding of the signature for {permit}, as defined by {EIP712}. - */ - // solhint-disable-next-line func-name-mixedcase - function DOMAIN_SEPARATOR() external view returns (bytes32); -} - - - -/** - * @title SafeERC20 - * @dev Wrappers around ERC20 operations that throw on failure (when the token - * contract returns false). Tokens that return no value (and instead revert or - * throw on failure) are also supported, non-reverting calls are assumed to be - * successful. - * To use this library you can add a `using SafeERC20 for IERC20;` statement to your contract, - * which allows you to call the safe operations as `token.safeTransfer(...)`, etc. - */ -library SafeERC20 { - using Address for address; - - function safeTransfer( - IERC20 token, - address to, - uint256 value - ) internal { - _callOptionalReturn(token, abi.encodeWithSelector(token.transfer.selector, to, value)); - } - - function safeTransferFrom( - IERC20 token, - address from, - address to, - uint256 value - ) internal { - _callOptionalReturn(token, abi.encodeWithSelector(token.transferFrom.selector, from, to, value)); - } - - /** - * @dev Deprecated. This function has issues similar to the ones found in - * {IERC20-approve}, and its usage is discouraged. - * - * Whenever possible, use {safeIncreaseAllowance} and - * {safeDecreaseAllowance} instead. - */ - function safeApprove( - IERC20 token, - address spender, - uint256 value - ) internal { - // safeApprove should only be called when setting an initial allowance, - // or when resetting it to zero. To increase and decrease it, use - // 'safeIncreaseAllowance' and 'safeDecreaseAllowance' - require( - (value == 0) || (token.allowance(address(this), spender) == 0), - "SafeERC20: approve from non-zero to non-zero allowance" - ); - _callOptionalReturn(token, abi.encodeWithSelector(token.approve.selector, spender, value)); - } - - function safeIncreaseAllowance( - IERC20 token, - address spender, - uint256 value - ) internal { - uint256 newAllowance = token.allowance(address(this), spender) + value; - _callOptionalReturn(token, abi.encodeWithSelector(token.approve.selector, spender, newAllowance)); - } - - function safeDecreaseAllowance( - IERC20 token, - address spender, - uint256 value - ) internal { - unchecked { - uint256 oldAllowance = token.allowance(address(this), spender); - require(oldAllowance >= value, "SafeERC20: decreased allowance below zero"); - uint256 newAllowance = oldAllowance - value; - _callOptionalReturn(token, abi.encodeWithSelector(token.approve.selector, spender, newAllowance)); - } - } - - function safePermit( - IERC20Permit token, - address owner, - address spender, - uint256 value, - uint256 deadline, - uint8 v, - bytes32 r, - bytes32 s - ) internal { - uint256 nonceBefore = token.nonces(owner); - token.permit(owner, spender, value, deadline, v, r, s); - uint256 nonceAfter = token.nonces(owner); - require(nonceAfter == nonceBefore + 1, "SafeERC20: permit did not succeed"); - } - - /** - * @dev Imitates a Solidity high-level call (i.e. a regular function call to a contract), relaxing the requirement - * on the return value: the return value is optional (but if data is returned, it must not be false). - * @param token The token targeted by the call. - * @param data The call data (encoded using abi.encode or one of its variants). - */ - function _callOptionalReturn(IERC20 token, bytes memory data) private { - // We need to perform a low level call here, to bypass Solidity's return data size checking mechanism, since - // we're implementing it ourselves. We use {Address.functionCall} to perform this call, which verifies that - // the target address contains contract code and also asserts for success in the low-level call. - - bytes memory returndata = address(token).functionCall(data, "SafeERC20: low-level call failed"); - if (returndata.length > 0) { - // Return data is optional - require(abi.decode(returndata, (bool)), "SafeERC20: ERC20 operation did not succeed"); - } - } -} - - - - - - - - - - - - - - -/** - * @dev Provides information about the current execution context, including the - * sender of the transaction and its data. While these are generally available - * via msg.sender and msg.data, they should not be accessed in such a direct - * manner, since when dealing with meta-transactions the account sending and - * paying for execution may not be the actual sender (as far as an application - * is concerned). - * - * This contract is only required for intermediate, library-like contracts. - */ -abstract contract Context { - function _msgSender() internal view virtual returns (address) { - return msg.sender; - } - - function _msgData() internal view virtual returns (bytes calldata) { - return msg.data; - } -} - - -/** - * @dev Contract module which provides a basic access control mechanism, where - * there is an account (an owner) that can be granted exclusive access to - * specific functions. - * - * By default, the owner account will be the one that deploys the contract. This - * can later be changed with {transferOwnership}. - * - * This module is used through inheritance. It will make available the modifier - * `onlyOwner`, which can be applied to your functions to restrict their use to - * the owner. - */ -abstract contract Ownable is Context { - address private _owner; - - event OwnershipTransferred(address indexed previousOwner, address indexed newOwner); - - /** - * @dev Initializes the contract setting the deployer as the initial owner. - */ - constructor() { - _transferOwnership(_msgSender()); - } - - /** - * @dev Throws if called by any account other than the owner. - */ - modifier onlyOwner() { - _checkOwner(); - _; - } - - /** - * @dev Returns the address of the current owner. - */ - function owner() public view virtual returns (address) { - return _owner; - } - - /** - * @dev Throws if the sender is not the owner. - */ - function _checkOwner() internal view virtual { - require(owner() == _msgSender(), "Ownable: caller is not the owner"); - } - - /** - * @dev Leaves the contract without owner. It will not be possible to call - * `onlyOwner` functions anymore. Can only be called by the current owner. - * - * NOTE: Renouncing ownership will leave the contract without an owner, - * thereby removing any functionality that is only available to the owner. - */ - function renounceOwnership() public virtual onlyOwner { - _transferOwnership(address(0)); - } - - /** - * @dev Transfers ownership of the contract to a new account (`newOwner`). - * Can only be called by the current owner. - */ - function transferOwnership(address newOwner) public virtual onlyOwner { - require(newOwner != address(0), "Ownable: new owner is the zero address"); - _transferOwnership(newOwner); - } - - /** - * @dev Transfers ownership of the contract to a new account (`newOwner`). - * Internal function without access restriction. - */ - function _transferOwnership(address newOwner) internal virtual { - address oldOwner = _owner; - _owner = newOwner; - emit OwnershipTransferred(oldOwner, newOwner); - } -} - - -contract Operator is Ownable { - address public operator; - uint256 constant baseRate = 10000; - - modifier onlyOperator { - require(msg.sender == owner() || msg.sender == operator, "no permission"); - _; - } - - function setOperator(address operator_) external onlyOwner { - operator = operator_; - } - - - function getCurrTime() external view returns(uint256) { - return block.timestamp; - } - - function getBlockNum() external view returns(uint256) { - return block.number; - } - -} - - - - - -/** - * @dev Library for managing - * https://en.wikipedia.org/wiki/Set_(abstract_data_type)[sets] of primitive - * types. - * - * Sets have the following properties: - * - * - Elements are added, removed, and checked for existence in constant time - * (O(1)). - * - Elements are enumerated in O(n). No guarantees are made on the ordering. - * - * ``` - * contract Example { - * // Add the library methods - * using EnumerableSet for EnumerableSet.AddressSet; - * - * // Declare a set state variable - * EnumerableSet.AddressSet private mySet; - * } - * ``` - * - * As of v3.3.0, sets of type `bytes32` (`Bytes32Set`), `address` (`AddressSet`) - * and `uint256` (`UintSet`) are supported. - * - * [WARNING] - * ==== - * Trying to delete such a structure from storage will likely result in data corruption, rendering the structure unusable. - * See https://github.com/ethereum/solidity/pull/11843[ethereum/solidity#11843] for more info. - * - * In order to clean an EnumerableSet, you can either remove all elements one by one or create a fresh instance using an array of EnumerableSet. - * ==== - */ - -library EnumerableSet { - // To implement this library for multiple types with as little code - // repetition as possible, we write it in terms of a generic Set type with - // bytes32 values. - // The Set implementation uses private functions, and user-facing - // implementations (such as AddressSet) are just wrappers around the - // underlying Set. - // This means that we can only create new EnumerableSets for types that fit - // in bytes32. - - struct Set { - // Storage of set values - bytes32[] _values; - // Position of the value in the `values` array, plus 1 because index 0 - // means a value is not in the set. - mapping(bytes32 => uint256) _indexes; - } - - /** - * @dev Add a value to a set. O(1). - * - * Returns true if the value was added to the set, that is if it was not - * already present. - */ - function _add(Set storage set, bytes32 value) private returns (bool) { - if (!_contains(set, value)) { - set._values.push(value); - // The value is stored at length-1, but we add 1 to all indexes - // and use 0 as a sentinel value - set._indexes[value] = set._values.length; - return true; - } else { - return false; - } - } - - /** - * @dev Removes a value from a set. O(1). - * - * Returns true if the value was removed from the set, that is if it was - * present. - */ - function _remove(Set storage set, bytes32 value) private returns (bool) { - // We read and store the value's index to prevent multiple reads from the same storage slot - uint256 valueIndex = set._indexes[value]; - - if (valueIndex != 0) { - // Equivalent to contains(set, value) - // To delete an element from the _values array in O(1), we swap the element to delete with the last one in - // the array, and then remove the last element (sometimes called as 'swap and pop'). - // This modifies the order of the array, as noted in {at}. - - uint256 toDeleteIndex = valueIndex - 1; - uint256 lastIndex = set._values.length - 1; - - if (lastIndex != toDeleteIndex) { - bytes32 lastValue = set._values[lastIndex]; - - // Move the last value to the index where the value to delete is - set._values[toDeleteIndex] = lastValue; - // Update the index for the moved value - set._indexes[lastValue] = valueIndex; // Replace lastValue's index to valueIndex - } - - // Delete the slot where the moved value was stored - set._values.pop(); - - // Delete the index for the deleted slot - delete set._indexes[value]; - - return true; - } else { - return false; - } - } - - /** - * @dev Returns true if the value is in the set. O(1). - */ - function _contains(Set storage set, bytes32 value) private view returns (bool) { - return set._indexes[value] != 0; - } - - /** - * @dev Returns the number of values on the set. O(1). - */ - function _length(Set storage set) private view returns (uint256) { - return set._values.length; - } - - /** - * @dev Returns the value stored at position `index` in the set. O(1). - * - * Note that there are no guarantees on the ordering of values inside the - * array, and it may change when more values are added or removed. - * - * Requirements: - * - * - `index` must be strictly less than {length}. - */ - function _at(Set storage set, uint256 index) private view returns (bytes32) { - return set._values[index]; - } - - /** - * @dev Return the entire set in an array - * - * WARNING: This operation will copy the entire storage to memory, which can be quite expensive. This is designed - * to mostly be used by view accessors that are queried without any gas fees. Developers should keep in mind that - * this function has an unbounded cost, and using it as part of a state-changing function may render the function - * uncallable if the set grows to a point where copying to memory consumes too much gas to fit in a block. - */ - function _values(Set storage set) private view returns (bytes32[] memory) { - return set._values; - } - - // Bytes32Set - - struct Bytes32Set { - Set _inner; - } - - /** - * @dev Add a value to a set. O(1). - * - * Returns true if the value was added to the set, that is if it was not - * already present. - */ - function add(Bytes32Set storage set, bytes32 value) internal returns (bool) { - return _add(set._inner, value); - } - - /** - * @dev Removes a value from a set. O(1). - * - * Returns true if the value was removed from the set, that is if it was - * present. - */ - function remove(Bytes32Set storage set, bytes32 value) internal returns (bool) { - return _remove(set._inner, value); - } - - /** - * @dev Returns true if the value is in the set. O(1). - */ - function contains(Bytes32Set storage set, bytes32 value) internal view returns (bool) { - return _contains(set._inner, value); - } - - /** - * @dev Returns the number of values in the set. O(1). - */ - function length(Bytes32Set storage set) internal view returns (uint256) { - return _length(set._inner); - } - - /** - * @dev Returns the value stored at position `index` in the set. O(1). - * - * Note that there are no guarantees on the ordering of values inside the - * array, and it may change when more values are added or removed. - * - * Requirements: - * - * - `index` must be strictly less than {length}. - */ - function at(Bytes32Set storage set, uint256 index) internal view returns (bytes32) { - return _at(set._inner, index); - } - - /** - * @dev Return the entire set in an array - * - * WARNING: This operation will copy the entire storage to memory, which can be quite expensive. This is designed - * to mostly be used by view accessors that are queried without any gas fees. Developers should keep in mind that - * this function has an unbounded cost, and using it as part of a state-changing function may render the function - * uncallable if the set grows to a point where copying to memory consumes too much gas to fit in a block. - */ - function values(Bytes32Set storage set) internal view returns (bytes32[] memory) { - return _values(set._inner); - } - - // AddressSet - - struct AddressSet { - Set _inner; - } - - /** - * @dev Add a value to a set. O(1). - * - * Returns true if the value was added to the set, that is if it was not - * already present. - */ - function add(AddressSet storage set, address value) internal returns (bool) { - return _add(set._inner, bytes32(uint256(uint160(value)))); - } - - /** - * @dev Removes a value from a set. O(1). - * - * Returns true if the value was removed from the set, that is if it was - * present. - */ - function remove(AddressSet storage set, address value) internal returns (bool) { - return _remove(set._inner, bytes32(uint256(uint160(value)))); - } - - /** - * @dev Returns true if the value is in the set. O(1). - */ - function contains(AddressSet storage set, address value) internal view returns (bool) { - return _contains(set._inner, bytes32(uint256(uint160(value)))); - } - - /** - * @dev Returns the number of values in the set. O(1). - */ - function length(AddressSet storage set) internal view returns (uint256) { - return _length(set._inner); - } - - /** - * @dev Returns the value stored at position `index` in the set. O(1). - * - * Note that there are no guarantees on the ordering of values inside the - * array, and it may change when more values are added or removed. - * - * Requirements: - * - * - `index` must be strictly less than {length}. - */ - function at(AddressSet storage set, uint256 index) internal view returns (address) { - return address(uint160(uint256(_at(set._inner, index)))); - } - - /** - * @dev Return the entire set in an array - * - * WARNING: This operation will copy the entire storage to memory, which can be quite expensive. This is designed - * to mostly be used by view accessors that are queried without any gas fees. Developers should keep in mind that - * this function has an unbounded cost, and using it as part of a state-changing function may render the function - * uncallable if the set grows to a point where copying to memory consumes too much gas to fit in a block. - */ - function values(AddressSet storage set) internal view returns (address[] memory) { - bytes32[] memory store = _values(set._inner); - address[] memory result; - - /// @solidity memory-safe-assembly - assembly { - result := store - } - - return result; - } - - // UintSet - - struct UintSet { - Set _inner; - } - - /** - * @dev Add a value to a set. O(1). - * - * Returns true if the value was added to the set, that is if it was not - * already present. - */ - function add(UintSet storage set, uint256 value) internal returns (bool) { - return _add(set._inner, bytes32(value)); - } - - /** - * @dev Removes a value from a set. O(1). - * - * Returns true if the value was removed from the set, that is if it was - * present. - */ - function remove(UintSet storage set, uint256 value) internal returns (bool) { - return _remove(set._inner, bytes32(value)); - } - - /** - * @dev Returns true if the value is in the set. O(1). - */ - function contains(UintSet storage set, uint256 value) internal view returns (bool) { - return _contains(set._inner, bytes32(value)); - } - - /** - * @dev Returns the number of values on the set. O(1). - */ - function length(UintSet storage set) internal view returns (uint256) { - return _length(set._inner); - } - - /** - * @dev Returns the value stored at position `index` in the set. O(1). - * - * Note that there are no guarantees on the ordering of values inside the - * array, and it may change when more values are added or removed. - * - * Requirements: - * - * - `index` must be strictly less than {length}. - */ - function at(UintSet storage set, uint256 index) internal view returns (uint256) { - return uint256(_at(set._inner, index)); - } - - /** - * @dev Return the entire set in an array - * - * WARNING: This operation will copy the entire storage to memory, which can be quite expensive. This is designed - * to mostly be used by view accessors that are queried without any gas fees. Developers should keep in mind that - * this function has an unbounded cost, and using it as part of a state-changing function may render the function - * uncallable if the set grows to a point where copying to memory consumes too much gas to fit in a block. - */ - function values(UintSet storage set) internal view returns (uint256[] memory) { - bytes32[] memory store = _values(set._inner); - uint256[] memory result; - - /// @solidity memory-safe-assembly - assembly { - result := store - } - - return result; - } -} - - -contract ActivityPool is Operator { - using SafeMath for uint256; - using SafeERC20 for IERC20; - using EnumerableSet for EnumerableSet.AddressSet; - using EnumerableSet for EnumerableSet.UintSet; - - event AddNewAct(uint256 id); - event Bet(address user, uint256 pID, uint256 bType, uint256 amount, uint256 time); - event SetPrize(uint256 pID, uint256 bType); - event Claim(address user, uint256 pID, uint256 bType, uint256 amount); - event RemovePeriodAct(uint256 pID); - - uint256 public constant muti = 1e18; - uint256 public periodID; - uint256 public betID; - - struct UserInfo { - address user; - uint256 pID; - uint256 amount; - uint256 betTime; - uint256 bType; - uint256 claimAmount; - } - - struct ActInfo { - string name; - string aName; - string bName; - address rewardToken; - uint256 startTime; - uint256 endTime; - uint256 minAmount; - uint256 maxAmount; - uint256 aAmount; - uint256 bAmount; - uint256 winType; - bool isBet; - } - - struct TimeInfo { - uint256 time; - uint256 aAmount; - uint256 bAmount; - } - - struct BestInfo { - address aUser; - address bUser; - uint256 aBet; - uint256 bBet; - } - - mapping(uint256 => BestInfo) bestInfo; - mapping(uint256 => uint256) public timeID; - mapping(uint256 => mapping(uint256 => TimeInfo)) public timeInfo; - mapping(address => mapping(uint256 => uint256)) public userBet; - mapping(uint256 => UserInfo) public betInfo; - mapping(uint256 => uint256) public perAmount; - mapping(uint256 => ActInfo) public actInfo; - mapping(uint256 => mapping(uint256 => string)) public descripName; - - mapping(address => EnumerableSet.UintSet) userPid; - mapping(uint256 => EnumerableSet.AddressSet) aUsers; - mapping(uint256 => EnumerableSet.AddressSet) bUsers; - EnumerableSet.UintSet activePeriod; - EnumerableSet.UintSet removePeriod; - - function addNewAct( - string memory name, - string memory aName, - string memory bName, - address token, - uint256 startTime, - uint256 endTime, - uint256 minAmount, - uint256 maxAmount - ) external onlyOperator { - - checkAdd(msg.sender, startTime, endTime, minAmount, maxAmount); - uint256 id = ++periodID; - actInfo[id].name = name; - actInfo[id].aName = aName; - actInfo[id].bName = bName; - actInfo[id].startTime = startTime; - actInfo[id].endTime = endTime; - actInfo[id].minAmount = minAmount; - actInfo[id].maxAmount = maxAmount; - actInfo[id].rewardToken = token; - descripName[id][1] = aName; - descripName[id][2] = bName; - activePeriod.add(id); - - emit AddNewAct(id); - } - - - function removePeriodAct(uint256 pID) external onlyOperator { - checkRemove(pID); - - activePeriod.remove(pID); - removePeriod.add(pID); - - emit RemovePeriodAct(pID); - } - - - function bet(uint256 pID, uint256 bType, uint256 amount) external payable { - checkBet(msg.sender, pID, bType, amount); - if(actInfo[pID].rewardToken == address(0)) { - require(msg.value == amount, "value err"); - } else { - require(msg.value == 0, "value amount err"); - } - - if(bType == 1) { - if(amount > bestInfo[pID].aBet) { - bestInfo[pID].aUser = msg.sender; - bestInfo[pID].aBet = amount; - } - } else { - if(amount > bestInfo[pID].bBet) { - bestInfo[pID].bUser = msg.sender; - bestInfo[pID].bBet = amount; - } - } - - userPid[msg.sender].add(pID); - uint256 id = ++betID; - userBet[msg.sender][pID] = id; - - if(bType == 1) { - aUsers[pID].add(msg.sender); - actInfo[pID].aAmount = actInfo[pID].aAmount.add(amount); - } else { - bUsers[pID].add(msg.sender); - actInfo[pID].bAmount = actInfo[pID].bAmount.add(amount); - } - - actInfo[pID].isBet = true; - betInfo[id].user = msg.sender; - betInfo[id].pID = pID; - betInfo[id].amount = amount; - betInfo[id].betTime = block.timestamp; - betInfo[id].bType = bType; - - uint256 tID = ++timeID[pID]; - timeInfo[pID][tID].time = block.timestamp; - timeInfo[pID][tID].aAmount = actInfo[pID].aAmount; - timeInfo[pID][tID].bAmount = actInfo[pID].bAmount; - - if(actInfo[pID].rewardToken != address(0)) { - IERC20(actInfo[pID].rewardToken).safeTransferFrom(msg.sender, address(this), amount); - } - emit Bet(msg.sender, pID, bType, amount, betInfo[id].betTime); - } - - function setPrize(uint256 pID, uint256 bType) external onlyOperator { - checkSetPrize(msg.sender, pID, bType); - - if(block.timestamp <= actInfo[pID].startTime) { - actInfo[pID].startTime = block.timestamp; - - } - actInfo[pID].endTime = block.timestamp; - - actInfo[pID].winType = bType; - perAmount[pID] = getPerAmount(pID, bType); - - emit SetPrize(pID, bType); - } - - function recive() public payable {} - - function claim(uint256 pID) external { - uint256 amount = checkClaim(msg.sender, pID); - - uint256 id = userBet[msg.sender][pID]; - betInfo[id].claimAmount = amount; - if(actInfo[pID].rewardToken != address(0)) { - IERC20(actInfo[pID].rewardToken).safeTransfer(msg.sender, amount); - } else { - payable(msg.sender).transfer(amount); - } - - emit Claim(msg.sender, pID, betInfo[id].bType, amount); - } - - function checkClaim(address user, uint256 pID) public view returns(uint256 amount) { - require(userPid[user].contains(pID), "not bet"); - uint256 id = userBet[user][pID]; - require(betInfo[id].user == user, "not user"); - require(actInfo[pID].winType != 0, "not prize"); - require(betInfo[id].claimAmount == 0, "has claim"); - - if(actInfo[pID].winType != 3) { - require(actInfo[pID].winType == betInfo[id].bType, "not right"); - amount = perAmount[pID].mul(betInfo[id].amount).div(muti); - require(amount > 0, "no amount"); - } else { - amount = betInfo[id].amount; - } - - return amount; - } - - function getActualRate( - address user, - uint256 pID, - uint256 bType, - uint256 amount - ) external view returns(uint256, uint256, bool) { - if(bType < 1 || bType > 2 || !activePeriod.contains(pID)) { - return (0, 0, false); - } else if(userBet[user][pID] != 0 || actInfo[pID].winType != 0 || amount == 0) { - (uint256 ra, uint256 rb) = getRate(pID, timeID[pID]); - return (ra, rb, false); - } else { - (uint256 aAmount, uint256 bAmount) = (actInfo[pID].aAmount, actInfo[pID].bAmount); - if(bType == 1) { - aAmount = aAmount.add(amount); - } else { - bAmount = bAmount.add(amount); - } - - uint256 total = aAmount.add(bAmount); - if(bAmount == 0 && aAmount != 0) { - return (muti, 0, true); - } - if(bAmount != 0 && aAmount == 0) { - return (0, muti, true); - } - return (total.mul(muti).div(aAmount), total.mul(muti).div(bAmount), true); - } - } - - function getRate(uint256 pID, uint256 tID) public view returns(uint256, uint256) { - (uint256 aAmount, uint256 bAmount) = (timeInfo[pID][tID].aAmount, timeInfo[pID][tID].bAmount); - uint256 total = aAmount.add(bAmount); - if(total == 0) { - return (0, 0); - } - if(bAmount == 0 && aAmount != 0) { - return (muti, 0); - } - if(bAmount != 0 && aAmount == 0) { - return (0, muti); - } - return (total.mul(muti).div(aAmount), total.mul(muti).div(bAmount)); - } - - function getBestInfo(uint256 pID) - external - view - returns(address aUser, address bUser, uint256 aBet, uint256 bBet, uint256 aReward, uint256 bReward) - { - aUser = bestInfo[pID].aUser; - bUser = bestInfo[pID].bUser; - aBet = bestInfo[pID].aBet; - bBet = bestInfo[pID].bBet; - aReward = getPerAmount(pID, 1).mul(aBet).div(muti); - bReward = getPerAmount(pID, 2).mul(bBet).div(muti); - } - - function getPerAmount(uint256 pID, uint256 bType) public view returns(uint256) { - uint256 total = actInfo[pID].aAmount.add(actInfo[pID].bAmount); - if(total == 0) { - return 0; - } - - if(actInfo[pID].winType == 3) { - return muti; - } - - if(bType == 1) { - if(actInfo[pID].aAmount == 0 || actInfo[pID].winType == 2) { - return 0; - } - return total.mul(muti).div(actInfo[pID].aAmount); - } - - if(bType == 2) { - if(actInfo[pID].bAmount == 0 || actInfo[pID].winType == 1) { - return 0; - } - return total.mul(muti).div(actInfo[pID].bAmount); - } - - return 0; - - } - - function checkSetPrize(address user, uint256 pID, uint256 bType) public view returns(bool) { - require(user == owner() || user == operator, "no permission"); - require(bType > 0 && bType <= 3, "type err"); - require(activePeriod.contains(pID), "not active"); - require(actInfo[pID].winType == 0, "has set"); - - return true; - } - - function checkBet( - address user, - uint256 pID, - uint256 bType, - uint256 amount - ) public view returns(bool) { - require(activePeriod.contains(pID), "not active"); - require(actInfo[pID].startTime <= block.timestamp, "not start"); - require(actInfo[pID].endTime > block.timestamp, "has end"); - require(!userPid[user].contains(pID), "has bet"); - require(bType > 0 && bType < 3, "type err"); - require(amount >= actInfo[pID].minAmount && amount <= actInfo[pID].maxAmount, "amount err"); - if(actInfo[pID].rewardToken != address(0)) { - require(IERC20(actInfo[pID].rewardToken).allowance(user, address(this)) >= amount, "not approve enough"); - require(IERC20(actInfo[pID].rewardToken).balanceOf(user) >= amount, "not enough"); - } else { - require(user.balance >= amount, "main token err"); - } - - return true; - } - - - function checkRemove(uint256 pID) public view returns(bool) { - require(activePeriod.contains(pID), "not in"); - require(!actInfo[pID].isBet, "has bet"); - - return true; - } - - function checkAdd( - address user, - uint256 startTime, - uint256 endTime, - uint256 minAmount, - uint256 maxAmount - ) public view returns(bool) { - require(user == owner() || user == operator, "no permission"); - require(startTime > block.timestamp, "startTime err"); - require(endTime > startTime, "endTime err"); - require(minAmount > 0 && maxAmount > minAmount, "amount err"); - - return true; - } - - function getStatus(uint256 pID) external view returns(uint256) { - if(!removePeriod.contains(pID) && !activePeriod.contains(pID)) { - return 5; - } else if(removePeriod.contains(pID)) { - return 6; - } else if(block.timestamp < actInfo[pID].startTime) { - return 1; - } else if ( - actInfo[pID].startTime <= block.timestamp && - actInfo[pID].endTime > block.timestamp - ) { - return 2; - } else if (actInfo[pID].endTime <= block.timestamp && actInfo[pID].winType == 0){ - return 3; - } else if(actInfo[pID].winType != 0) { - return 4; - } - return 0; - } - - function getUserPidNum(address user) external view returns(uint256) { - return userPid[user].length(); - } - - function getUserPid(address user, uint256 index) external view returns(uint256) { - return userPid[user].at(index); - } - - function getAUsersNum(uint256 pID) external view returns(uint256) { - return aUsers[pID].length(); - } - - function getAUsers(uint256 pID, uint256 index) external view returns(address) { - return aUsers[pID].at(index); - } - - function getBUsersNum(uint256 pID) external view returns(uint256) { - return bUsers[pID].length(); - } - - function getBUsers(uint256 pID, uint256 index) external view returns(address) { - return bUsers[pID].at(index); - } - - function getActivePeriodNum() external view returns(uint256) { - return activePeriod.length(); - } - - function getActivePeriod(uint256 index) external view returns(uint256) { - return activePeriod.at(index); - } - - function getRemovePeriodNum() external view returns(uint256) { - return removePeriod.length(); - } - - function getRemovePeriod(uint256 index) external view returns(uint256) { - return removePeriod.at(index); - } -} \ No newline at end of file diff --git a/app/api/uploads/ActivityPool-1729821817840-171758606.sol b/app/api/uploads/ActivityPool-1729821817840-171758606.sol deleted file mode 100644 index daf3372..0000000 --- a/app/api/uploads/ActivityPool-1729821817840-171758606.sol +++ /dev/null @@ -1,1648 +0,0 @@ -// SPDX-License-Identifier: MIT -// OpenZeppelin Contracts (last updated v4.7.0) (utils/Address.sol) - -pragma solidity ^0.8.1; - -/** - * @dev Collection of functions related to the address type - */ -library Address { - /** - * @dev Returns true if `account` is a contract. - * - * [IMPORTANT] - * ==== - * It is unsafe to assume that an address for which this function returns - * false is an externally-owned account (EOA) and not a contract. - * - * Among others, `isContract` will return false for the following - * types of addresses: - * - * - an externally-owned account - * - a contract in construction - * - an address where a contract will be created - * - an address where a contract lived, but was destroyed - * ==== - * - * [IMPORTANT] - * ==== - * You shouldn't rely on `isContract` to protect against flash loan attacks! - * - * Preventing calls from contracts is highly discouraged. It breaks composability, breaks support for smart wallets - * like Gnosis Safe, and does not provide security since it can be circumvented by calling from a contract - * constructor. - * ==== - */ - function isContract(address account) internal view returns (bool) { - // This method relies on extcodesize/address.code.length, which returns 0 - // for contracts in construction, since the code is only stored at the end - // of the constructor execution. - - return account.code.length > 0; - } - - /** - * @dev Replacement for Solidity's `transfer`: sends `amount` wei to - * `recipient`, forwarding all available gas and reverting on errors. - * - * https://eips.ethereum.org/EIPS/eip-1884[EIP1884] increases the gas cost - * of certain opcodes, possibly making contracts go over the 2300 gas limit - * imposed by `transfer`, making them unable to receive funds via - * `transfer`. {sendValue} removes this limitation. - * - * https://diligence.consensys.net/posts/2019/09/stop-using-soliditys-transfer-now/[Learn more]. - * - * IMPORTANT: because control is transferred to `recipient`, care must be - * taken to not create reentrancy vulnerabilities. Consider using - * {ReentrancyGuard} or the - * https://solidity.readthedocs.io/en/v0.5.11/security-considerations.html#use-the-checks-effects-interactions-pattern[checks-effects-interactions pattern]. - */ - function sendValue(address payable recipient, uint256 amount) internal { - require(address(this).balance >= amount, "Address: insufficient balance"); - - (bool success, ) = recipient.call{value: amount}(""); - require(success, "Address: unable to send value, recipient may have reverted"); - } - - /** - * @dev Performs a Solidity function call using a low level `call`. A - * plain `call` is an unsafe replacement for a function call: use this - * function instead. - * - * If `target` reverts with a revert reason, it is bubbled up by this - * function (like regular Solidity function calls). - * - * Returns the raw returned data. To convert to the expected return value, - * use https://solidity.readthedocs.io/en/latest/units-and-global-variables.html?highlight=abi.decode#abi-encoding-and-decoding-functions[`abi.decode`]. - * - * Requirements: - * - * - `target` must be a contract. - * - calling `target` with `data` must not revert. - * - * _Available since v3.1._ - */ - function functionCall(address target, bytes memory data) internal returns (bytes memory) { - return functionCallWithValue(target, data, 0, "Address: low-level call failed"); - } - - /** - * @dev Same as {xref-Address-functionCall-address-bytes-}[`functionCall`], but with - * `errorMessage` as a fallback revert reason when `target` reverts. - * - * _Available since v3.1._ - */ - function functionCall( - address target, - bytes memory data, - string memory errorMessage - ) internal returns (bytes memory) { - return functionCallWithValue(target, data, 0, errorMessage); - } - - /** - * @dev Same as {xref-Address-functionCall-address-bytes-}[`functionCall`], - * but also transferring `value` wei to `target`. - * - * Requirements: - * - * - the calling contract must have an ETH balance of at least `value`. - * - the called Solidity function must be `payable`. - * - * _Available since v3.1._ - */ - function functionCallWithValue( - address target, - bytes memory data, - uint256 value - ) internal returns (bytes memory) { - return functionCallWithValue(target, data, value, "Address: low-level call with value failed"); - } - - /** - * @dev Same as {xref-Address-functionCallWithValue-address-bytes-uint256-}[`functionCallWithValue`], but - * with `errorMessage` as a fallback revert reason when `target` reverts. - * - * _Available since v3.1._ - */ - function functionCallWithValue( - address target, - bytes memory data, - uint256 value, - string memory errorMessage - ) internal returns (bytes memory) { - require(address(this).balance >= value, "Address: insufficient balance for call"); - (bool success, bytes memory returndata) = target.call{value: value}(data); - return verifyCallResultFromTarget(target, success, returndata, errorMessage); - } - - /** - * @dev Same as {xref-Address-functionCall-address-bytes-}[`functionCall`], - * but performing a static call. - * - * _Available since v3.3._ - */ - function functionStaticCall(address target, bytes memory data) internal view returns (bytes memory) { - return functionStaticCall(target, data, "Address: low-level static call failed"); - } - - /** - * @dev Same as {xref-Address-functionCall-address-bytes-string-}[`functionCall`], - * but performing a static call. - * - * _Available since v3.3._ - */ - function functionStaticCall( - address target, - bytes memory data, - string memory errorMessage - ) internal view returns (bytes memory) { - (bool success, bytes memory returndata) = target.staticcall(data); - return verifyCallResultFromTarget(target, success, returndata, errorMessage); - } - - /** - * @dev Same as {xref-Address-functionCall-address-bytes-}[`functionCall`], - * but performing a delegate call. - * - * _Available since v3.4._ - */ - function functionDelegateCall(address target, bytes memory data) internal returns (bytes memory) { - return functionDelegateCall(target, data, "Address: low-level delegate call failed"); - } - - /** - * @dev Same as {xref-Address-functionCall-address-bytes-string-}[`functionCall`], - * but performing a delegate call. - * - * _Available since v3.4._ - */ - function functionDelegateCall( - address target, - bytes memory data, - string memory errorMessage - ) internal returns (bytes memory) { - (bool success, bytes memory returndata) = target.delegatecall(data); - return verifyCallResultFromTarget(target, success, returndata, errorMessage); - } - - /** - * @dev Tool to verify that a low level call to smart-contract was successful, and revert (either by bubbling - * the revert reason or using the provided one) in case of unsuccessful call or if target was not a contract. - * - * _Available since v4.8._ - */ - function verifyCallResultFromTarget( - address target, - bool success, - bytes memory returndata, - string memory errorMessage - ) internal view returns (bytes memory) { - if (success) { - if (returndata.length == 0) { - // only check isContract if the call was successful and the return data is empty - // otherwise we already know that it was a contract - require(isContract(target), "Address: call to non-contract"); - } - return returndata; - } else { - _revert(returndata, errorMessage); - } - } - - /** - * @dev Tool to verify that a low level call was successful, and revert if it wasn't, either by bubbling the - * revert reason or using the provided one. - * - * _Available since v4.3._ - */ - function verifyCallResult( - bool success, - bytes memory returndata, - string memory errorMessage - ) internal pure returns (bytes memory) { - if (success) { - return returndata; - } else { - _revert(returndata, errorMessage); - } - } - - function _revert(bytes memory returndata, string memory errorMessage) private pure { - // Look for revert reason and bubble it up if present - if (returndata.length > 0) { - // The easiest way to bubble the revert reason is using memory via assembly - /// @solidity memory-safe-assembly - assembly { - let returndata_size := mload(returndata) - revert(add(32, returndata), returndata_size) - } - } else { - revert(errorMessage); - } - } -} - -// OpenZeppelin Contracts (last updated v4.6.0) (token/ERC20/IERC20.sol) - - - -/** - * @dev Interface of the ERC20 standard as defined in the EIP. - */ -interface IERC20 { - /** - * @dev Emitted when `value` tokens are moved from one account (`from`) to - * another (`to`). - * - * Note that `value` may be zero. - */ - event Transfer(address indexed from, address indexed to, uint256 value); - - /** - * @dev Emitted when the allowance of a `spender` for an `owner` is set by - * a call to {approve}. `value` is the new allowance. - */ - event Approval(address indexed owner, address indexed spender, uint256 value); - - /** - * @dev Returns the amount of tokens in existence. - */ - function totalSupply() external view returns (uint256); - - /** - * @dev Returns the amount of tokens owned by `account`. - */ - function balanceOf(address account) external view returns (uint256); - - /** - * @dev Moves `amount` tokens from the caller's account to `to`. - * - * Returns a boolean value indicating whether the operation succeeded. - * - * Emits a {Transfer} event. - */ - function transfer(address to, uint256 amount) external returns (bool); - - /** - * @dev Returns the remaining number of tokens that `spender` will be - * allowed to spend on behalf of `owner` through {transferFrom}. This is - * zero by default. - * - * This value changes when {approve} or {transferFrom} are called. - */ - function allowance(address owner, address spender) external view returns (uint256); - - /** - * @dev Sets `amount` as the allowance of `spender` over the caller's tokens. - * - * Returns a boolean value indicating whether the operation succeeded. - * - * IMPORTANT: Beware that changing an allowance with this method brings the risk - * that someone may use both the old and the new allowance by unfortunate - * transaction ordering. One possible solution to mitigate this race - * condition is to first reduce the spender's allowance to 0 and set the - * desired value afterwards: - * https://github.com/ethereum/EIPs/issues/20#issuecomment-263524729 - * - * Emits an {Approval} event. - */ - function approve(address spender, uint256 amount) external returns (bool); - - /** - * @dev Moves `amount` tokens from `from` to `to` using the - * allowance mechanism. `amount` is then deducted from the caller's - * allowance. - * - * Returns a boolean value indicating whether the operation succeeded. - * - * Emits a {Transfer} event. - */ - function transferFrom( - address from, - address to, - uint256 amount - ) external returns (bool); - - - function mint(address account_, uint256 amount_) external; - - function burn(uint256 amount) external; - -} - - - - - - - - - - - -/** - * @dev Wrappers over Solidity's arithmetic operations with added overflow - * checks. - * - * Arithmetic operations in Solidity wrap on overflow. This can easily result - * in bugs, because programmers usually assume that an overflow raises an - * error, which is the standard behavior in high level programming languages. - * `SafeMath` restores this intuition by reverting the transaction when an - * operation overflows. - * - * Using this library instead of the unchecked operations eliminates an entire - * class of bugs, so it's recommended to use it always. - */ -library SafeMath { - /** - * @dev Returns the addition of two unsigned integers, reverting on - * overflow. - * - * Counterpart to Solidity's `+` operator. - * - * Requirements: - * - * - Addition cannot overflow. - */ - function add(uint256 a, uint256 b) internal pure returns (uint256) { - uint256 c = a + b; - require(c >= a, "SafeMath: addition overflow"); - - return c; - } - - /** - * @dev Returns the subtraction of two unsigned integers, reverting on - * overflow (when the result is negative). - * - * Counterpart to Solidity's `-` operator. - * - * Requirements: - * - * - Subtraction cannot overflow. - */ - function sub(uint256 a, uint256 b) internal pure returns (uint256) { - return sub(a, b, "SafeMath: subtraction overflow"); - } - - /** - * @dev Returns the subtraction of two unsigned integers, reverting with custom message on - * overflow (when the result is negative). - * - * Counterpart to Solidity's `-` operator. - * - * Requirements: - * - * - Subtraction cannot overflow. - */ - function sub( - uint256 a, - uint256 b, - string memory errorMessage - ) internal pure returns (uint256) { - require(b <= a, errorMessage); - uint256 c = a - b; - - return c; - } - - /** - * @dev Returns the multiplication of two unsigned integers, reverting on - * overflow. - * - * Counterpart to Solidity's `*` operator. - * - * Requirements: - * - * - Multiplication cannot overflow. - */ - function mul(uint256 a, uint256 b) internal pure returns (uint256) { - // Gas optimization: this is cheaper than requiring 'a' not being zero, but the - // benefit is lost if 'b' is also tested. - // See: https://github.com/OpenZeppelin/openzeppelin-contracts/pull/522 - if (a == 0) { - return 0; - } - - uint256 c = a * b; - require(c / a == b, "SafeMath: multiplication overflow"); - - return c; - } - - /** - * @dev Returns the integer division of two unsigned integers. Reverts on - * division by zero. The result is rounded towards zero. - * - * Counterpart to Solidity's `/` operator. Note: this function uses a - * `revert` opcode (which leaves remaining gas untouched) while Solidity - * uses an invalid opcode to revert (consuming all remaining gas). - * - * Requirements: - * - * - The divisor cannot be zero. - */ - function div(uint256 a, uint256 b) internal pure returns (uint256) { - return div(a, b, "SafeMath: division by zero"); - } - - /** - * @dev Returns the integer division of two unsigned integers. Reverts with custom message on - * division by zero. The result is rounded towards zero. - * - * Counterpart to Solidity's `/` operator. Note: this function uses a - * `revert` opcode (which leaves remaining gas untouched) while Solidity - * uses an invalid opcode to revert (consuming all remaining gas). - * - * Requirements: - * - * - The divisor cannot be zero. - */ - function div( - uint256 a, - uint256 b, - string memory errorMessage - ) internal pure returns (uint256) { - require(b > 0, errorMessage); - uint256 c = a / b; - // assert(a == b * c + a % b); // There is no case in which this doesn't hold - - return c; - } - - /** - * @dev Returns the remainder of dividing two unsigned integers. (unsigned integer modulo), - * Reverts when dividing by zero. - * - * Counterpart to Solidity's `%` operator. This function uses a `revert` - * opcode (which leaves remaining gas untouched) while Solidity uses an - * invalid opcode to revert (consuming all remaining gas). - * - * Requirements: - * - * - The divisor cannot be zero. - */ - function mod(uint256 a, uint256 b) internal pure returns (uint256) { - return mod(a, b, "SafeMath: modulo by zero"); - } - - /** - * @dev Returns the remainder of dividing two unsigned integers. (unsigned integer modulo), - * Reverts with custom message when dividing by zero. - * - * Counterpart to Solidity's `%` operator. This function uses a `revert` - * opcode (which leaves remaining gas untouched) while Solidity uses an - * invalid opcode to revert (consuming all remaining gas). - * - * Requirements: - * - * - The divisor cannot be zero. - */ - function mod( - uint256 a, - uint256 b, - string memory errorMessage - ) internal pure returns (uint256) { - require(b != 0, errorMessage); - return a % b; - } - - // babylonian method (https://en.wikipedia.org/wiki/Methods_of_computing_square_roots#Babylonian_method) - function sqrrt(uint256 a) internal pure returns (uint256 c) { - if (a > 3) { - c = a; - uint256 b = add(div(a, 2), 1); - while (b < c) { - c = b; - b = div(add(div(a, b), b), 2); - } - } else if (a != 0) { - c = 1; - } - } - - /* - * Expects percentage to be trailed by 00, - */ - function percentageAmount(uint256 total_, uint8 percentage_) internal pure returns (uint256 percentAmount_) { - return div(mul(total_, percentage_), 1000); - } - - /* - * Expects percentage to be trailed by 00, - */ - function substractPercentage(uint256 total_, uint8 percentageToSub_) internal pure returns (uint256 result_) { - return sub(total_, div(mul(total_, percentageToSub_), 1000)); - } - - function percentageOfTotal(uint256 part_, uint256 total_) internal pure returns (uint256 percent_) { - return div(mul(part_, 100), total_); - } - - /** - * Taken from Hypersonic https://github.com/M2629/HyperSonic/blob/main/Math.sol - * @dev Returns the average of two numbers. The result is rounded towards - * zero. - */ - function average(uint256 a, uint256 b) internal pure returns (uint256) { - // (a + b) / 2 can overflow, so we distribute - return (a / 2) + (b / 2) + (((a % 2) + (b % 2)) / 2); - } - - function quadraticPricing(uint256 payment_, uint256 multiplier_) internal pure returns (uint256) { - return sqrrt(mul(multiplier_, payment_)); - } - - function bondingCurve(uint256 supply_, uint256 multiplier_) internal pure returns (uint256) { - return mul(multiplier_, supply_); - } -} - -// OpenZeppelin Contracts (last updated v4.7.0) (token/ERC20/utils/SafeERC20.sol) - - - - - -// OpenZeppelin Contracts v4.4.1 (token/ERC20/extensions/draft-IERC20Permit.sol) - - - -/** - * @dev Interface of the ERC20 Permit extension allowing approvals to be made via signatures, as defined in - * https://eips.ethereum.org/EIPS/eip-2612[EIP-2612]. - * - * Adds the {permit} method, which can be used to change an account's ERC20 allowance (see {IERC20-allowance}) by - * presenting a message signed by the account. By not relying on {IERC20-approve}, the token holder account doesn't - * need to send a transaction, and thus is not required to hold Ether at all. - */ -interface IERC20Permit { - /** - * @dev Sets `value` as the allowance of `spender` over ``owner``'s tokens, - * given ``owner``'s signed approval. - * - * IMPORTANT: The same issues {IERC20-approve} has related to transaction - * ordering also apply here. - * - * Emits an {Approval} event. - * - * Requirements: - * - * - `spender` cannot be the zero address. - * - `deadline` must be a timestamp in the future. - * - `v`, `r` and `s` must be a valid `secp256k1` signature from `owner` - * over the EIP712-formatted function arguments. - * - the signature must use ``owner``'s current nonce (see {nonces}). - * - * For more information on the signature format, see the - * https://eips.ethereum.org/EIPS/eip-2612#specification[relevant EIP - * section]. - */ - function permit( - address owner, - address spender, - uint256 value, - uint256 deadline, - uint8 v, - bytes32 r, - bytes32 s - ) external; - - /** - * @dev Returns the current nonce for `owner`. This value must be - * included whenever a signature is generated for {permit}. - * - * Every successful call to {permit} increases ``owner``'s nonce by one. This - * prevents a signature from being used multiple times. - */ - function nonces(address owner) external view returns (uint256); - - /** - * @dev Returns the domain separator used in the encoding of the signature for {permit}, as defined by {EIP712}. - */ - // solhint-disable-next-line func-name-mixedcase - function DOMAIN_SEPARATOR() external view returns (bytes32); -} - - - -/** - * @title SafeERC20 - * @dev Wrappers around ERC20 operations that throw on failure (when the token - * contract returns false). Tokens that return no value (and instead revert or - * throw on failure) are also supported, non-reverting calls are assumed to be - * successful. - * To use this library you can add a `using SafeERC20 for IERC20;` statement to your contract, - * which allows you to call the safe operations as `token.safeTransfer(...)`, etc. - */ -library SafeERC20 { - using Address for address; - - function safeTransfer( - IERC20 token, - address to, - uint256 value - ) internal { - _callOptionalReturn(token, abi.encodeWithSelector(token.transfer.selector, to, value)); - } - - function safeTransferFrom( - IERC20 token, - address from, - address to, - uint256 value - ) internal { - _callOptionalReturn(token, abi.encodeWithSelector(token.transferFrom.selector, from, to, value)); - } - - /** - * @dev Deprecated. This function has issues similar to the ones found in - * {IERC20-approve}, and its usage is discouraged. - * - * Whenever possible, use {safeIncreaseAllowance} and - * {safeDecreaseAllowance} instead. - */ - function safeApprove( - IERC20 token, - address spender, - uint256 value - ) internal { - // safeApprove should only be called when setting an initial allowance, - // or when resetting it to zero. To increase and decrease it, use - // 'safeIncreaseAllowance' and 'safeDecreaseAllowance' - require( - (value == 0) || (token.allowance(address(this), spender) == 0), - "SafeERC20: approve from non-zero to non-zero allowance" - ); - _callOptionalReturn(token, abi.encodeWithSelector(token.approve.selector, spender, value)); - } - - function safeIncreaseAllowance( - IERC20 token, - address spender, - uint256 value - ) internal { - uint256 newAllowance = token.allowance(address(this), spender) + value; - _callOptionalReturn(token, abi.encodeWithSelector(token.approve.selector, spender, newAllowance)); - } - - function safeDecreaseAllowance( - IERC20 token, - address spender, - uint256 value - ) internal { - unchecked { - uint256 oldAllowance = token.allowance(address(this), spender); - require(oldAllowance >= value, "SafeERC20: decreased allowance below zero"); - uint256 newAllowance = oldAllowance - value; - _callOptionalReturn(token, abi.encodeWithSelector(token.approve.selector, spender, newAllowance)); - } - } - - function safePermit( - IERC20Permit token, - address owner, - address spender, - uint256 value, - uint256 deadline, - uint8 v, - bytes32 r, - bytes32 s - ) internal { - uint256 nonceBefore = token.nonces(owner); - token.permit(owner, spender, value, deadline, v, r, s); - uint256 nonceAfter = token.nonces(owner); - require(nonceAfter == nonceBefore + 1, "SafeERC20: permit did not succeed"); - } - - /** - * @dev Imitates a Solidity high-level call (i.e. a regular function call to a contract), relaxing the requirement - * on the return value: the return value is optional (but if data is returned, it must not be false). - * @param token The token targeted by the call. - * @param data The call data (encoded using abi.encode or one of its variants). - */ - function _callOptionalReturn(IERC20 token, bytes memory data) private { - // We need to perform a low level call here, to bypass Solidity's return data size checking mechanism, since - // we're implementing it ourselves. We use {Address.functionCall} to perform this call, which verifies that - // the target address contains contract code and also asserts for success in the low-level call. - - bytes memory returndata = address(token).functionCall(data, "SafeERC20: low-level call failed"); - if (returndata.length > 0) { - // Return data is optional - require(abi.decode(returndata, (bool)), "SafeERC20: ERC20 operation did not succeed"); - } - } -} - - - - - - - - - - - - - - -/** - * @dev Provides information about the current execution context, including the - * sender of the transaction and its data. While these are generally available - * via msg.sender and msg.data, they should not be accessed in such a direct - * manner, since when dealing with meta-transactions the account sending and - * paying for execution may not be the actual sender (as far as an application - * is concerned). - * - * This contract is only required for intermediate, library-like contracts. - */ -abstract contract Context { - function _msgSender() internal view virtual returns (address) { - return msg.sender; - } - - function _msgData() internal view virtual returns (bytes calldata) { - return msg.data; - } -} - - -/** - * @dev Contract module which provides a basic access control mechanism, where - * there is an account (an owner) that can be granted exclusive access to - * specific functions. - * - * By default, the owner account will be the one that deploys the contract. This - * can later be changed with {transferOwnership}. - * - * This module is used through inheritance. It will make available the modifier - * `onlyOwner`, which can be applied to your functions to restrict their use to - * the owner. - */ -abstract contract Ownable is Context { - address private _owner; - - event OwnershipTransferred(address indexed previousOwner, address indexed newOwner); - - /** - * @dev Initializes the contract setting the deployer as the initial owner. - */ - constructor() { - _transferOwnership(_msgSender()); - } - - /** - * @dev Throws if called by any account other than the owner. - */ - modifier onlyOwner() { - _checkOwner(); - _; - } - - /** - * @dev Returns the address of the current owner. - */ - function owner() public view virtual returns (address) { - return _owner; - } - - /** - * @dev Throws if the sender is not the owner. - */ - function _checkOwner() internal view virtual { - require(owner() == _msgSender(), "Ownable: caller is not the owner"); - } - - /** - * @dev Leaves the contract without owner. It will not be possible to call - * `onlyOwner` functions anymore. Can only be called by the current owner. - * - * NOTE: Renouncing ownership will leave the contract without an owner, - * thereby removing any functionality that is only available to the owner. - */ - function renounceOwnership() public virtual onlyOwner { - _transferOwnership(address(0)); - } - - /** - * @dev Transfers ownership of the contract to a new account (`newOwner`). - * Can only be called by the current owner. - */ - function transferOwnership(address newOwner) public virtual onlyOwner { - require(newOwner != address(0), "Ownable: new owner is the zero address"); - _transferOwnership(newOwner); - } - - /** - * @dev Transfers ownership of the contract to a new account (`newOwner`). - * Internal function without access restriction. - */ - function _transferOwnership(address newOwner) internal virtual { - address oldOwner = _owner; - _owner = newOwner; - emit OwnershipTransferred(oldOwner, newOwner); - } -} - - -contract Operator is Ownable { - address public operator; - uint256 constant baseRate = 10000; - - modifier onlyOperator { - require(msg.sender == owner() || msg.sender == operator, "no permission"); - _; - } - - function setOperator(address operator_) external onlyOwner { - operator = operator_; - } - - - function getCurrTime() external view returns(uint256) { - return block.timestamp; - } - - function getBlockNum() external view returns(uint256) { - return block.number; - } - -} - - - - - -/** - * @dev Library for managing - * https://en.wikipedia.org/wiki/Set_(abstract_data_type)[sets] of primitive - * types. - * - * Sets have the following properties: - * - * - Elements are added, removed, and checked for existence in constant time - * (O(1)). - * - Elements are enumerated in O(n). No guarantees are made on the ordering. - * - * ``` - * contract Example { - * // Add the library methods - * using EnumerableSet for EnumerableSet.AddressSet; - * - * // Declare a set state variable - * EnumerableSet.AddressSet private mySet; - * } - * ``` - * - * As of v3.3.0, sets of type `bytes32` (`Bytes32Set`), `address` (`AddressSet`) - * and `uint256` (`UintSet`) are supported. - * - * [WARNING] - * ==== - * Trying to delete such a structure from storage will likely result in data corruption, rendering the structure unusable. - * See https://github.com/ethereum/solidity/pull/11843[ethereum/solidity#11843] for more info. - * - * In order to clean an EnumerableSet, you can either remove all elements one by one or create a fresh instance using an array of EnumerableSet. - * ==== - */ - -library EnumerableSet { - // To implement this library for multiple types with as little code - // repetition as possible, we write it in terms of a generic Set type with - // bytes32 values. - // The Set implementation uses private functions, and user-facing - // implementations (such as AddressSet) are just wrappers around the - // underlying Set. - // This means that we can only create new EnumerableSets for types that fit - // in bytes32. - - struct Set { - // Storage of set values - bytes32[] _values; - // Position of the value in the `values` array, plus 1 because index 0 - // means a value is not in the set. - mapping(bytes32 => uint256) _indexes; - } - - /** - * @dev Add a value to a set. O(1). - * - * Returns true if the value was added to the set, that is if it was not - * already present. - */ - function _add(Set storage set, bytes32 value) private returns (bool) { - if (!_contains(set, value)) { - set._values.push(value); - // The value is stored at length-1, but we add 1 to all indexes - // and use 0 as a sentinel value - set._indexes[value] = set._values.length; - return true; - } else { - return false; - } - } - - /** - * @dev Removes a value from a set. O(1). - * - * Returns true if the value was removed from the set, that is if it was - * present. - */ - function _remove(Set storage set, bytes32 value) private returns (bool) { - // We read and store the value's index to prevent multiple reads from the same storage slot - uint256 valueIndex = set._indexes[value]; - - if (valueIndex != 0) { - // Equivalent to contains(set, value) - // To delete an element from the _values array in O(1), we swap the element to delete with the last one in - // the array, and then remove the last element (sometimes called as 'swap and pop'). - // This modifies the order of the array, as noted in {at}. - - uint256 toDeleteIndex = valueIndex - 1; - uint256 lastIndex = set._values.length - 1; - - if (lastIndex != toDeleteIndex) { - bytes32 lastValue = set._values[lastIndex]; - - // Move the last value to the index where the value to delete is - set._values[toDeleteIndex] = lastValue; - // Update the index for the moved value - set._indexes[lastValue] = valueIndex; // Replace lastValue's index to valueIndex - } - - // Delete the slot where the moved value was stored - set._values.pop(); - - // Delete the index for the deleted slot - delete set._indexes[value]; - - return true; - } else { - return false; - } - } - - /** - * @dev Returns true if the value is in the set. O(1). - */ - function _contains(Set storage set, bytes32 value) private view returns (bool) { - return set._indexes[value] != 0; - } - - /** - * @dev Returns the number of values on the set. O(1). - */ - function _length(Set storage set) private view returns (uint256) { - return set._values.length; - } - - /** - * @dev Returns the value stored at position `index` in the set. O(1). - * - * Note that there are no guarantees on the ordering of values inside the - * array, and it may change when more values are added or removed. - * - * Requirements: - * - * - `index` must be strictly less than {length}. - */ - function _at(Set storage set, uint256 index) private view returns (bytes32) { - return set._values[index]; - } - - /** - * @dev Return the entire set in an array - * - * WARNING: This operation will copy the entire storage to memory, which can be quite expensive. This is designed - * to mostly be used by view accessors that are queried without any gas fees. Developers should keep in mind that - * this function has an unbounded cost, and using it as part of a state-changing function may render the function - * uncallable if the set grows to a point where copying to memory consumes too much gas to fit in a block. - */ - function _values(Set storage set) private view returns (bytes32[] memory) { - return set._values; - } - - // Bytes32Set - - struct Bytes32Set { - Set _inner; - } - - /** - * @dev Add a value to a set. O(1). - * - * Returns true if the value was added to the set, that is if it was not - * already present. - */ - function add(Bytes32Set storage set, bytes32 value) internal returns (bool) { - return _add(set._inner, value); - } - - /** - * @dev Removes a value from a set. O(1). - * - * Returns true if the value was removed from the set, that is if it was - * present. - */ - function remove(Bytes32Set storage set, bytes32 value) internal returns (bool) { - return _remove(set._inner, value); - } - - /** - * @dev Returns true if the value is in the set. O(1). - */ - function contains(Bytes32Set storage set, bytes32 value) internal view returns (bool) { - return _contains(set._inner, value); - } - - /** - * @dev Returns the number of values in the set. O(1). - */ - function length(Bytes32Set storage set) internal view returns (uint256) { - return _length(set._inner); - } - - /** - * @dev Returns the value stored at position `index` in the set. O(1). - * - * Note that there are no guarantees on the ordering of values inside the - * array, and it may change when more values are added or removed. - * - * Requirements: - * - * - `index` must be strictly less than {length}. - */ - function at(Bytes32Set storage set, uint256 index) internal view returns (bytes32) { - return _at(set._inner, index); - } - - /** - * @dev Return the entire set in an array - * - * WARNING: This operation will copy the entire storage to memory, which can be quite expensive. This is designed - * to mostly be used by view accessors that are queried without any gas fees. Developers should keep in mind that - * this function has an unbounded cost, and using it as part of a state-changing function may render the function - * uncallable if the set grows to a point where copying to memory consumes too much gas to fit in a block. - */ - function values(Bytes32Set storage set) internal view returns (bytes32[] memory) { - return _values(set._inner); - } - - // AddressSet - - struct AddressSet { - Set _inner; - } - - /** - * @dev Add a value to a set. O(1). - * - * Returns true if the value was added to the set, that is if it was not - * already present. - */ - function add(AddressSet storage set, address value) internal returns (bool) { - return _add(set._inner, bytes32(uint256(uint160(value)))); - } - - /** - * @dev Removes a value from a set. O(1). - * - * Returns true if the value was removed from the set, that is if it was - * present. - */ - function remove(AddressSet storage set, address value) internal returns (bool) { - return _remove(set._inner, bytes32(uint256(uint160(value)))); - } - - /** - * @dev Returns true if the value is in the set. O(1). - */ - function contains(AddressSet storage set, address value) internal view returns (bool) { - return _contains(set._inner, bytes32(uint256(uint160(value)))); - } - - /** - * @dev Returns the number of values in the set. O(1). - */ - function length(AddressSet storage set) internal view returns (uint256) { - return _length(set._inner); - } - - /** - * @dev Returns the value stored at position `index` in the set. O(1). - * - * Note that there are no guarantees on the ordering of values inside the - * array, and it may change when more values are added or removed. - * - * Requirements: - * - * - `index` must be strictly less than {length}. - */ - function at(AddressSet storage set, uint256 index) internal view returns (address) { - return address(uint160(uint256(_at(set._inner, index)))); - } - - /** - * @dev Return the entire set in an array - * - * WARNING: This operation will copy the entire storage to memory, which can be quite expensive. This is designed - * to mostly be used by view accessors that are queried without any gas fees. Developers should keep in mind that - * this function has an unbounded cost, and using it as part of a state-changing function may render the function - * uncallable if the set grows to a point where copying to memory consumes too much gas to fit in a block. - */ - function values(AddressSet storage set) internal view returns (address[] memory) { - bytes32[] memory store = _values(set._inner); - address[] memory result; - - /// @solidity memory-safe-assembly - assembly { - result := store - } - - return result; - } - - // UintSet - - struct UintSet { - Set _inner; - } - - /** - * @dev Add a value to a set. O(1). - * - * Returns true if the value was added to the set, that is if it was not - * already present. - */ - function add(UintSet storage set, uint256 value) internal returns (bool) { - return _add(set._inner, bytes32(value)); - } - - /** - * @dev Removes a value from a set. O(1). - * - * Returns true if the value was removed from the set, that is if it was - * present. - */ - function remove(UintSet storage set, uint256 value) internal returns (bool) { - return _remove(set._inner, bytes32(value)); - } - - /** - * @dev Returns true if the value is in the set. O(1). - */ - function contains(UintSet storage set, uint256 value) internal view returns (bool) { - return _contains(set._inner, bytes32(value)); - } - - /** - * @dev Returns the number of values on the set. O(1). - */ - function length(UintSet storage set) internal view returns (uint256) { - return _length(set._inner); - } - - /** - * @dev Returns the value stored at position `index` in the set. O(1). - * - * Note that there are no guarantees on the ordering of values inside the - * array, and it may change when more values are added or removed. - * - * Requirements: - * - * - `index` must be strictly less than {length}. - */ - function at(UintSet storage set, uint256 index) internal view returns (uint256) { - return uint256(_at(set._inner, index)); - } - - /** - * @dev Return the entire set in an array - * - * WARNING: This operation will copy the entire storage to memory, which can be quite expensive. This is designed - * to mostly be used by view accessors that are queried without any gas fees. Developers should keep in mind that - * this function has an unbounded cost, and using it as part of a state-changing function may render the function - * uncallable if the set grows to a point where copying to memory consumes too much gas to fit in a block. - */ - function values(UintSet storage set) internal view returns (uint256[] memory) { - bytes32[] memory store = _values(set._inner); - uint256[] memory result; - - /// @solidity memory-safe-assembly - assembly { - result := store - } - - return result; - } -} - - -contract ActivityPool is Operator { - using SafeMath for uint256; - using SafeERC20 for IERC20; - using EnumerableSet for EnumerableSet.AddressSet; - using EnumerableSet for EnumerableSet.UintSet; - - event AddNewAct(uint256 id); - event Bet(address user, uint256 pID, uint256 bType, uint256 amount, uint256 time); - event SetPrize(uint256 pID, uint256 bType); - event Claim(address user, uint256 pID, uint256 bType, uint256 amount); - event RemovePeriodAct(uint256 pID); - - uint256 public constant muti = 1e18; - uint256 public periodID; - uint256 public betID; - - struct UserInfo { - address user; - uint256 pID; - uint256 amount; - uint256 betTime; - uint256 bType; - uint256 claimAmount; - } - - struct ActInfo { - string name; - string aName; - string bName; - address rewardToken; - uint256 startTime; - uint256 endTime; - uint256 minAmount; - uint256 maxAmount; - uint256 aAmount; - uint256 bAmount; - uint256 winType; - bool isBet; - } - - struct TimeInfo { - uint256 time; - uint256 aAmount; - uint256 bAmount; - } - - struct BestInfo { - address aUser; - address bUser; - uint256 aBet; - uint256 bBet; - } - - mapping(uint256 => BestInfo) bestInfo; - mapping(uint256 => uint256) public timeID; - mapping(uint256 => mapping(uint256 => TimeInfo)) public timeInfo; - mapping(address => mapping(uint256 => uint256)) public userBet; - mapping(uint256 => UserInfo) public betInfo; - mapping(uint256 => uint256) public perAmount; - mapping(uint256 => ActInfo) public actInfo; - mapping(uint256 => mapping(uint256 => string)) public descripName; - - mapping(address => EnumerableSet.UintSet) userPid; - mapping(uint256 => EnumerableSet.AddressSet) aUsers; - mapping(uint256 => EnumerableSet.AddressSet) bUsers; - EnumerableSet.UintSet activePeriod; - EnumerableSet.UintSet removePeriod; - - function addNewAct( - string memory name, - string memory aName, - string memory bName, - address token, - uint256 startTime, - uint256 endTime, - uint256 minAmount, - uint256 maxAmount - ) external onlyOperator { - - checkAdd(msg.sender, startTime, endTime, minAmount, maxAmount); - uint256 id = ++periodID; - actInfo[id].name = name; - actInfo[id].aName = aName; - actInfo[id].bName = bName; - actInfo[id].startTime = startTime; - actInfo[id].endTime = endTime; - actInfo[id].minAmount = minAmount; - actInfo[id].maxAmount = maxAmount; - actInfo[id].rewardToken = token; - descripName[id][1] = aName; - descripName[id][2] = bName; - activePeriod.add(id); - - emit AddNewAct(id); - } - - - function removePeriodAct(uint256 pID) external onlyOperator { - checkRemove(pID); - - activePeriod.remove(pID); - removePeriod.add(pID); - - emit RemovePeriodAct(pID); - } - - - function bet(uint256 pID, uint256 bType, uint256 amount) external payable { - checkBet(msg.sender, pID, bType, amount); - if(actInfo[pID].rewardToken == address(0)) { - require(msg.value == amount, "value err"); - } else { - require(msg.value == 0, "value amount err"); - } - - if(bType == 1) { - if(amount > bestInfo[pID].aBet) { - bestInfo[pID].aUser = msg.sender; - bestInfo[pID].aBet = amount; - } - } else { - if(amount > bestInfo[pID].bBet) { - bestInfo[pID].bUser = msg.sender; - bestInfo[pID].bBet = amount; - } - } - - userPid[msg.sender].add(pID); - uint256 id = ++betID; - userBet[msg.sender][pID] = id; - - if(bType == 1) { - aUsers[pID].add(msg.sender); - actInfo[pID].aAmount = actInfo[pID].aAmount.add(amount); - } else { - bUsers[pID].add(msg.sender); - actInfo[pID].bAmount = actInfo[pID].bAmount.add(amount); - } - - actInfo[pID].isBet = true; - betInfo[id].user = msg.sender; - betInfo[id].pID = pID; - betInfo[id].amount = amount; - betInfo[id].betTime = block.timestamp; - betInfo[id].bType = bType; - - uint256 tID = ++timeID[pID]; - timeInfo[pID][tID].time = block.timestamp; - timeInfo[pID][tID].aAmount = actInfo[pID].aAmount; - timeInfo[pID][tID].bAmount = actInfo[pID].bAmount; - - if(actInfo[pID].rewardToken != address(0)) { - IERC20(actInfo[pID].rewardToken).safeTransferFrom(msg.sender, address(this), amount); - } - emit Bet(msg.sender, pID, bType, amount, betInfo[id].betTime); - } - - function setPrize(uint256 pID, uint256 bType) external onlyOperator { - checkSetPrize(msg.sender, pID, bType); - - if(block.timestamp <= actInfo[pID].startTime) { - actInfo[pID].startTime = block.timestamp; - - } - actInfo[pID].endTime = block.timestamp; - - actInfo[pID].winType = bType; - perAmount[pID] = getPerAmount(pID, bType); - - emit SetPrize(pID, bType); - } - - function recive() public payable {} - - function claim(uint256 pID) external { - uint256 amount = checkClaim(msg.sender, pID); - - uint256 id = userBet[msg.sender][pID]; - betInfo[id].claimAmount = amount; - if(actInfo[pID].rewardToken != address(0)) { - IERC20(actInfo[pID].rewardToken).safeTransfer(msg.sender, amount); - } else { - payable(msg.sender).transfer(amount); - } - - emit Claim(msg.sender, pID, betInfo[id].bType, amount); - } - - function checkClaim(address user, uint256 pID) public view returns(uint256 amount) { - require(userPid[user].contains(pID), "not bet"); - uint256 id = userBet[user][pID]; - require(betInfo[id].user == user, "not user"); - require(actInfo[pID].winType != 0, "not prize"); - require(betInfo[id].claimAmount == 0, "has claim"); - - if(actInfo[pID].winType != 3) { - require(actInfo[pID].winType == betInfo[id].bType, "not right"); - amount = perAmount[pID].mul(betInfo[id].amount).div(muti); - require(amount > 0, "no amount"); - } else { - amount = betInfo[id].amount; - } - - return amount; - } - - function getActualRate( - address user, - uint256 pID, - uint256 bType, - uint256 amount - ) external view returns(uint256, uint256, bool) { - if(bType < 1 || bType > 2 || !activePeriod.contains(pID)) { - return (0, 0, false); - } else if(userBet[user][pID] != 0 || actInfo[pID].winType != 0 || amount == 0) { - (uint256 ra, uint256 rb) = getRate(pID, timeID[pID]); - return (ra, rb, false); - } else { - (uint256 aAmount, uint256 bAmount) = (actInfo[pID].aAmount, actInfo[pID].bAmount); - if(bType == 1) { - aAmount = aAmount.add(amount); - } else { - bAmount = bAmount.add(amount); - } - - uint256 total = aAmount.add(bAmount); - if(bAmount == 0 && aAmount != 0) { - return (muti, 0, true); - } - if(bAmount != 0 && aAmount == 0) { - return (0, muti, true); - } - return (total.mul(muti).div(aAmount), total.mul(muti).div(bAmount), true); - } - } - - function getRate(uint256 pID, uint256 tID) public view returns(uint256, uint256) { - (uint256 aAmount, uint256 bAmount) = (timeInfo[pID][tID].aAmount, timeInfo[pID][tID].bAmount); - uint256 total = aAmount.add(bAmount); - if(total == 0) { - return (0, 0); - } - if(bAmount == 0 && aAmount != 0) { - return (muti, 0); - } - if(bAmount != 0 && aAmount == 0) { - return (0, muti); - } - return (total.mul(muti).div(aAmount), total.mul(muti).div(bAmount)); - } - - function getBestInfo(uint256 pID) - external - view - returns(address aUser, address bUser, uint256 aBet, uint256 bBet, uint256 aReward, uint256 bReward) - { - aUser = bestInfo[pID].aUser; - bUser = bestInfo[pID].bUser; - aBet = bestInfo[pID].aBet; - bBet = bestInfo[pID].bBet; - aReward = getPerAmount(pID, 1).mul(aBet).div(muti); - bReward = getPerAmount(pID, 2).mul(bBet).div(muti); - } - - function getPerAmount(uint256 pID, uint256 bType) public view returns(uint256) { - uint256 total = actInfo[pID].aAmount.add(actInfo[pID].bAmount); - if(total == 0) { - return 0; - } - - if(actInfo[pID].winType == 3) { - return muti; - } - - if(bType == 1) { - if(actInfo[pID].aAmount == 0 || actInfo[pID].winType == 2) { - return 0; - } - return total.mul(muti).div(actInfo[pID].aAmount); - } - - if(bType == 2) { - if(actInfo[pID].bAmount == 0 || actInfo[pID].winType == 1) { - return 0; - } - return total.mul(muti).div(actInfo[pID].bAmount); - } - - return 0; - - } - - function checkSetPrize(address user, uint256 pID, uint256 bType) public view returns(bool) { - require(user == owner() || user == operator, "no permission"); - require(bType > 0 && bType <= 3, "type err"); - require(activePeriod.contains(pID), "not active"); - require(actInfo[pID].winType == 0, "has set"); - - return true; - } - - function checkBet( - address user, - uint256 pID, - uint256 bType, - uint256 amount - ) public view returns(bool) { - require(activePeriod.contains(pID), "not active"); - require(actInfo[pID].startTime <= block.timestamp, "not start"); - require(actInfo[pID].endTime > block.timestamp, "has end"); - require(!userPid[user].contains(pID), "has bet"); - require(bType > 0 && bType < 3, "type err"); - require(amount >= actInfo[pID].minAmount && amount <= actInfo[pID].maxAmount, "amount err"); - if(actInfo[pID].rewardToken != address(0)) { - require(IERC20(actInfo[pID].rewardToken).allowance(user, address(this)) >= amount, "not approve enough"); - require(IERC20(actInfo[pID].rewardToken).balanceOf(user) >= amount, "not enough"); - } else { - require(user.balance >= amount, "main token err"); - } - - return true; - } - - - function checkRemove(uint256 pID) public view returns(bool) { - require(activePeriod.contains(pID), "not in"); - require(!actInfo[pID].isBet, "has bet"); - - return true; - } - - function checkAdd( - address user, - uint256 startTime, - uint256 endTime, - uint256 minAmount, - uint256 maxAmount - ) public view returns(bool) { - require(user == owner() || user == operator, "no permission"); - require(startTime > block.timestamp, "startTime err"); - require(endTime > startTime, "endTime err"); - require(minAmount > 0 && maxAmount > minAmount, "amount err"); - - return true; - } - - function getStatus(uint256 pID) external view returns(uint256) { - if(!removePeriod.contains(pID) && !activePeriod.contains(pID)) { - return 5; - } else if(removePeriod.contains(pID)) { - return 6; - } else if(block.timestamp < actInfo[pID].startTime) { - return 1; - } else if ( - actInfo[pID].startTime <= block.timestamp && - actInfo[pID].endTime > block.timestamp - ) { - return 2; - } else if (actInfo[pID].endTime <= block.timestamp && actInfo[pID].winType == 0){ - return 3; - } else if(actInfo[pID].winType != 0) { - return 4; - } - return 0; - } - - function getUserPidNum(address user) external view returns(uint256) { - return userPid[user].length(); - } - - function getUserPid(address user, uint256 index) external view returns(uint256) { - return userPid[user].at(index); - } - - function getAUsersNum(uint256 pID) external view returns(uint256) { - return aUsers[pID].length(); - } - - function getAUsers(uint256 pID, uint256 index) external view returns(address) { - return aUsers[pID].at(index); - } - - function getBUsersNum(uint256 pID) external view returns(uint256) { - return bUsers[pID].length(); - } - - function getBUsers(uint256 pID, uint256 index) external view returns(address) { - return bUsers[pID].at(index); - } - - function getActivePeriodNum() external view returns(uint256) { - return activePeriod.length(); - } - - function getActivePeriod(uint256 index) external view returns(uint256) { - return activePeriod.at(index); - } - - function getRemovePeriodNum() external view returns(uint256) { - return removePeriod.length(); - } - - function getRemovePeriod(uint256 index) external view returns(uint256) { - return removePeriod.at(index); - } -} \ No newline at end of file diff --git a/app/api/uploads/ActivityPool-1729821940759-282179510.sol b/app/api/uploads/ActivityPool-1729821940759-282179510.sol deleted file mode 100644 index daf3372..0000000 --- a/app/api/uploads/ActivityPool-1729821940759-282179510.sol +++ /dev/null @@ -1,1648 +0,0 @@ -// SPDX-License-Identifier: MIT -// OpenZeppelin Contracts (last updated v4.7.0) (utils/Address.sol) - -pragma solidity ^0.8.1; - -/** - * @dev Collection of functions related to the address type - */ -library Address { - /** - * @dev Returns true if `account` is a contract. - * - * [IMPORTANT] - * ==== - * It is unsafe to assume that an address for which this function returns - * false is an externally-owned account (EOA) and not a contract. - * - * Among others, `isContract` will return false for the following - * types of addresses: - * - * - an externally-owned account - * - a contract in construction - * - an address where a contract will be created - * - an address where a contract lived, but was destroyed - * ==== - * - * [IMPORTANT] - * ==== - * You shouldn't rely on `isContract` to protect against flash loan attacks! - * - * Preventing calls from contracts is highly discouraged. It breaks composability, breaks support for smart wallets - * like Gnosis Safe, and does not provide security since it can be circumvented by calling from a contract - * constructor. - * ==== - */ - function isContract(address account) internal view returns (bool) { - // This method relies on extcodesize/address.code.length, which returns 0 - // for contracts in construction, since the code is only stored at the end - // of the constructor execution. - - return account.code.length > 0; - } - - /** - * @dev Replacement for Solidity's `transfer`: sends `amount` wei to - * `recipient`, forwarding all available gas and reverting on errors. - * - * https://eips.ethereum.org/EIPS/eip-1884[EIP1884] increases the gas cost - * of certain opcodes, possibly making contracts go over the 2300 gas limit - * imposed by `transfer`, making them unable to receive funds via - * `transfer`. {sendValue} removes this limitation. - * - * https://diligence.consensys.net/posts/2019/09/stop-using-soliditys-transfer-now/[Learn more]. - * - * IMPORTANT: because control is transferred to `recipient`, care must be - * taken to not create reentrancy vulnerabilities. Consider using - * {ReentrancyGuard} or the - * https://solidity.readthedocs.io/en/v0.5.11/security-considerations.html#use-the-checks-effects-interactions-pattern[checks-effects-interactions pattern]. - */ - function sendValue(address payable recipient, uint256 amount) internal { - require(address(this).balance >= amount, "Address: insufficient balance"); - - (bool success, ) = recipient.call{value: amount}(""); - require(success, "Address: unable to send value, recipient may have reverted"); - } - - /** - * @dev Performs a Solidity function call using a low level `call`. A - * plain `call` is an unsafe replacement for a function call: use this - * function instead. - * - * If `target` reverts with a revert reason, it is bubbled up by this - * function (like regular Solidity function calls). - * - * Returns the raw returned data. To convert to the expected return value, - * use https://solidity.readthedocs.io/en/latest/units-and-global-variables.html?highlight=abi.decode#abi-encoding-and-decoding-functions[`abi.decode`]. - * - * Requirements: - * - * - `target` must be a contract. - * - calling `target` with `data` must not revert. - * - * _Available since v3.1._ - */ - function functionCall(address target, bytes memory data) internal returns (bytes memory) { - return functionCallWithValue(target, data, 0, "Address: low-level call failed"); - } - - /** - * @dev Same as {xref-Address-functionCall-address-bytes-}[`functionCall`], but with - * `errorMessage` as a fallback revert reason when `target` reverts. - * - * _Available since v3.1._ - */ - function functionCall( - address target, - bytes memory data, - string memory errorMessage - ) internal returns (bytes memory) { - return functionCallWithValue(target, data, 0, errorMessage); - } - - /** - * @dev Same as {xref-Address-functionCall-address-bytes-}[`functionCall`], - * but also transferring `value` wei to `target`. - * - * Requirements: - * - * - the calling contract must have an ETH balance of at least `value`. - * - the called Solidity function must be `payable`. - * - * _Available since v3.1._ - */ - function functionCallWithValue( - address target, - bytes memory data, - uint256 value - ) internal returns (bytes memory) { - return functionCallWithValue(target, data, value, "Address: low-level call with value failed"); - } - - /** - * @dev Same as {xref-Address-functionCallWithValue-address-bytes-uint256-}[`functionCallWithValue`], but - * with `errorMessage` as a fallback revert reason when `target` reverts. - * - * _Available since v3.1._ - */ - function functionCallWithValue( - address target, - bytes memory data, - uint256 value, - string memory errorMessage - ) internal returns (bytes memory) { - require(address(this).balance >= value, "Address: insufficient balance for call"); - (bool success, bytes memory returndata) = target.call{value: value}(data); - return verifyCallResultFromTarget(target, success, returndata, errorMessage); - } - - /** - * @dev Same as {xref-Address-functionCall-address-bytes-}[`functionCall`], - * but performing a static call. - * - * _Available since v3.3._ - */ - function functionStaticCall(address target, bytes memory data) internal view returns (bytes memory) { - return functionStaticCall(target, data, "Address: low-level static call failed"); - } - - /** - * @dev Same as {xref-Address-functionCall-address-bytes-string-}[`functionCall`], - * but performing a static call. - * - * _Available since v3.3._ - */ - function functionStaticCall( - address target, - bytes memory data, - string memory errorMessage - ) internal view returns (bytes memory) { - (bool success, bytes memory returndata) = target.staticcall(data); - return verifyCallResultFromTarget(target, success, returndata, errorMessage); - } - - /** - * @dev Same as {xref-Address-functionCall-address-bytes-}[`functionCall`], - * but performing a delegate call. - * - * _Available since v3.4._ - */ - function functionDelegateCall(address target, bytes memory data) internal returns (bytes memory) { - return functionDelegateCall(target, data, "Address: low-level delegate call failed"); - } - - /** - * @dev Same as {xref-Address-functionCall-address-bytes-string-}[`functionCall`], - * but performing a delegate call. - * - * _Available since v3.4._ - */ - function functionDelegateCall( - address target, - bytes memory data, - string memory errorMessage - ) internal returns (bytes memory) { - (bool success, bytes memory returndata) = target.delegatecall(data); - return verifyCallResultFromTarget(target, success, returndata, errorMessage); - } - - /** - * @dev Tool to verify that a low level call to smart-contract was successful, and revert (either by bubbling - * the revert reason or using the provided one) in case of unsuccessful call or if target was not a contract. - * - * _Available since v4.8._ - */ - function verifyCallResultFromTarget( - address target, - bool success, - bytes memory returndata, - string memory errorMessage - ) internal view returns (bytes memory) { - if (success) { - if (returndata.length == 0) { - // only check isContract if the call was successful and the return data is empty - // otherwise we already know that it was a contract - require(isContract(target), "Address: call to non-contract"); - } - return returndata; - } else { - _revert(returndata, errorMessage); - } - } - - /** - * @dev Tool to verify that a low level call was successful, and revert if it wasn't, either by bubbling the - * revert reason or using the provided one. - * - * _Available since v4.3._ - */ - function verifyCallResult( - bool success, - bytes memory returndata, - string memory errorMessage - ) internal pure returns (bytes memory) { - if (success) { - return returndata; - } else { - _revert(returndata, errorMessage); - } - } - - function _revert(bytes memory returndata, string memory errorMessage) private pure { - // Look for revert reason and bubble it up if present - if (returndata.length > 0) { - // The easiest way to bubble the revert reason is using memory via assembly - /// @solidity memory-safe-assembly - assembly { - let returndata_size := mload(returndata) - revert(add(32, returndata), returndata_size) - } - } else { - revert(errorMessage); - } - } -} - -// OpenZeppelin Contracts (last updated v4.6.0) (token/ERC20/IERC20.sol) - - - -/** - * @dev Interface of the ERC20 standard as defined in the EIP. - */ -interface IERC20 { - /** - * @dev Emitted when `value` tokens are moved from one account (`from`) to - * another (`to`). - * - * Note that `value` may be zero. - */ - event Transfer(address indexed from, address indexed to, uint256 value); - - /** - * @dev Emitted when the allowance of a `spender` for an `owner` is set by - * a call to {approve}. `value` is the new allowance. - */ - event Approval(address indexed owner, address indexed spender, uint256 value); - - /** - * @dev Returns the amount of tokens in existence. - */ - function totalSupply() external view returns (uint256); - - /** - * @dev Returns the amount of tokens owned by `account`. - */ - function balanceOf(address account) external view returns (uint256); - - /** - * @dev Moves `amount` tokens from the caller's account to `to`. - * - * Returns a boolean value indicating whether the operation succeeded. - * - * Emits a {Transfer} event. - */ - function transfer(address to, uint256 amount) external returns (bool); - - /** - * @dev Returns the remaining number of tokens that `spender` will be - * allowed to spend on behalf of `owner` through {transferFrom}. This is - * zero by default. - * - * This value changes when {approve} or {transferFrom} are called. - */ - function allowance(address owner, address spender) external view returns (uint256); - - /** - * @dev Sets `amount` as the allowance of `spender` over the caller's tokens. - * - * Returns a boolean value indicating whether the operation succeeded. - * - * IMPORTANT: Beware that changing an allowance with this method brings the risk - * that someone may use both the old and the new allowance by unfortunate - * transaction ordering. One possible solution to mitigate this race - * condition is to first reduce the spender's allowance to 0 and set the - * desired value afterwards: - * https://github.com/ethereum/EIPs/issues/20#issuecomment-263524729 - * - * Emits an {Approval} event. - */ - function approve(address spender, uint256 amount) external returns (bool); - - /** - * @dev Moves `amount` tokens from `from` to `to` using the - * allowance mechanism. `amount` is then deducted from the caller's - * allowance. - * - * Returns a boolean value indicating whether the operation succeeded. - * - * Emits a {Transfer} event. - */ - function transferFrom( - address from, - address to, - uint256 amount - ) external returns (bool); - - - function mint(address account_, uint256 amount_) external; - - function burn(uint256 amount) external; - -} - - - - - - - - - - - -/** - * @dev Wrappers over Solidity's arithmetic operations with added overflow - * checks. - * - * Arithmetic operations in Solidity wrap on overflow. This can easily result - * in bugs, because programmers usually assume that an overflow raises an - * error, which is the standard behavior in high level programming languages. - * `SafeMath` restores this intuition by reverting the transaction when an - * operation overflows. - * - * Using this library instead of the unchecked operations eliminates an entire - * class of bugs, so it's recommended to use it always. - */ -library SafeMath { - /** - * @dev Returns the addition of two unsigned integers, reverting on - * overflow. - * - * Counterpart to Solidity's `+` operator. - * - * Requirements: - * - * - Addition cannot overflow. - */ - function add(uint256 a, uint256 b) internal pure returns (uint256) { - uint256 c = a + b; - require(c >= a, "SafeMath: addition overflow"); - - return c; - } - - /** - * @dev Returns the subtraction of two unsigned integers, reverting on - * overflow (when the result is negative). - * - * Counterpart to Solidity's `-` operator. - * - * Requirements: - * - * - Subtraction cannot overflow. - */ - function sub(uint256 a, uint256 b) internal pure returns (uint256) { - return sub(a, b, "SafeMath: subtraction overflow"); - } - - /** - * @dev Returns the subtraction of two unsigned integers, reverting with custom message on - * overflow (when the result is negative). - * - * Counterpart to Solidity's `-` operator. - * - * Requirements: - * - * - Subtraction cannot overflow. - */ - function sub( - uint256 a, - uint256 b, - string memory errorMessage - ) internal pure returns (uint256) { - require(b <= a, errorMessage); - uint256 c = a - b; - - return c; - } - - /** - * @dev Returns the multiplication of two unsigned integers, reverting on - * overflow. - * - * Counterpart to Solidity's `*` operator. - * - * Requirements: - * - * - Multiplication cannot overflow. - */ - function mul(uint256 a, uint256 b) internal pure returns (uint256) { - // Gas optimization: this is cheaper than requiring 'a' not being zero, but the - // benefit is lost if 'b' is also tested. - // See: https://github.com/OpenZeppelin/openzeppelin-contracts/pull/522 - if (a == 0) { - return 0; - } - - uint256 c = a * b; - require(c / a == b, "SafeMath: multiplication overflow"); - - return c; - } - - /** - * @dev Returns the integer division of two unsigned integers. Reverts on - * division by zero. The result is rounded towards zero. - * - * Counterpart to Solidity's `/` operator. Note: this function uses a - * `revert` opcode (which leaves remaining gas untouched) while Solidity - * uses an invalid opcode to revert (consuming all remaining gas). - * - * Requirements: - * - * - The divisor cannot be zero. - */ - function div(uint256 a, uint256 b) internal pure returns (uint256) { - return div(a, b, "SafeMath: division by zero"); - } - - /** - * @dev Returns the integer division of two unsigned integers. Reverts with custom message on - * division by zero. The result is rounded towards zero. - * - * Counterpart to Solidity's `/` operator. Note: this function uses a - * `revert` opcode (which leaves remaining gas untouched) while Solidity - * uses an invalid opcode to revert (consuming all remaining gas). - * - * Requirements: - * - * - The divisor cannot be zero. - */ - function div( - uint256 a, - uint256 b, - string memory errorMessage - ) internal pure returns (uint256) { - require(b > 0, errorMessage); - uint256 c = a / b; - // assert(a == b * c + a % b); // There is no case in which this doesn't hold - - return c; - } - - /** - * @dev Returns the remainder of dividing two unsigned integers. (unsigned integer modulo), - * Reverts when dividing by zero. - * - * Counterpart to Solidity's `%` operator. This function uses a `revert` - * opcode (which leaves remaining gas untouched) while Solidity uses an - * invalid opcode to revert (consuming all remaining gas). - * - * Requirements: - * - * - The divisor cannot be zero. - */ - function mod(uint256 a, uint256 b) internal pure returns (uint256) { - return mod(a, b, "SafeMath: modulo by zero"); - } - - /** - * @dev Returns the remainder of dividing two unsigned integers. (unsigned integer modulo), - * Reverts with custom message when dividing by zero. - * - * Counterpart to Solidity's `%` operator. This function uses a `revert` - * opcode (which leaves remaining gas untouched) while Solidity uses an - * invalid opcode to revert (consuming all remaining gas). - * - * Requirements: - * - * - The divisor cannot be zero. - */ - function mod( - uint256 a, - uint256 b, - string memory errorMessage - ) internal pure returns (uint256) { - require(b != 0, errorMessage); - return a % b; - } - - // babylonian method (https://en.wikipedia.org/wiki/Methods_of_computing_square_roots#Babylonian_method) - function sqrrt(uint256 a) internal pure returns (uint256 c) { - if (a > 3) { - c = a; - uint256 b = add(div(a, 2), 1); - while (b < c) { - c = b; - b = div(add(div(a, b), b), 2); - } - } else if (a != 0) { - c = 1; - } - } - - /* - * Expects percentage to be trailed by 00, - */ - function percentageAmount(uint256 total_, uint8 percentage_) internal pure returns (uint256 percentAmount_) { - return div(mul(total_, percentage_), 1000); - } - - /* - * Expects percentage to be trailed by 00, - */ - function substractPercentage(uint256 total_, uint8 percentageToSub_) internal pure returns (uint256 result_) { - return sub(total_, div(mul(total_, percentageToSub_), 1000)); - } - - function percentageOfTotal(uint256 part_, uint256 total_) internal pure returns (uint256 percent_) { - return div(mul(part_, 100), total_); - } - - /** - * Taken from Hypersonic https://github.com/M2629/HyperSonic/blob/main/Math.sol - * @dev Returns the average of two numbers. The result is rounded towards - * zero. - */ - function average(uint256 a, uint256 b) internal pure returns (uint256) { - // (a + b) / 2 can overflow, so we distribute - return (a / 2) + (b / 2) + (((a % 2) + (b % 2)) / 2); - } - - function quadraticPricing(uint256 payment_, uint256 multiplier_) internal pure returns (uint256) { - return sqrrt(mul(multiplier_, payment_)); - } - - function bondingCurve(uint256 supply_, uint256 multiplier_) internal pure returns (uint256) { - return mul(multiplier_, supply_); - } -} - -// OpenZeppelin Contracts (last updated v4.7.0) (token/ERC20/utils/SafeERC20.sol) - - - - - -// OpenZeppelin Contracts v4.4.1 (token/ERC20/extensions/draft-IERC20Permit.sol) - - - -/** - * @dev Interface of the ERC20 Permit extension allowing approvals to be made via signatures, as defined in - * https://eips.ethereum.org/EIPS/eip-2612[EIP-2612]. - * - * Adds the {permit} method, which can be used to change an account's ERC20 allowance (see {IERC20-allowance}) by - * presenting a message signed by the account. By not relying on {IERC20-approve}, the token holder account doesn't - * need to send a transaction, and thus is not required to hold Ether at all. - */ -interface IERC20Permit { - /** - * @dev Sets `value` as the allowance of `spender` over ``owner``'s tokens, - * given ``owner``'s signed approval. - * - * IMPORTANT: The same issues {IERC20-approve} has related to transaction - * ordering also apply here. - * - * Emits an {Approval} event. - * - * Requirements: - * - * - `spender` cannot be the zero address. - * - `deadline` must be a timestamp in the future. - * - `v`, `r` and `s` must be a valid `secp256k1` signature from `owner` - * over the EIP712-formatted function arguments. - * - the signature must use ``owner``'s current nonce (see {nonces}). - * - * For more information on the signature format, see the - * https://eips.ethereum.org/EIPS/eip-2612#specification[relevant EIP - * section]. - */ - function permit( - address owner, - address spender, - uint256 value, - uint256 deadline, - uint8 v, - bytes32 r, - bytes32 s - ) external; - - /** - * @dev Returns the current nonce for `owner`. This value must be - * included whenever a signature is generated for {permit}. - * - * Every successful call to {permit} increases ``owner``'s nonce by one. This - * prevents a signature from being used multiple times. - */ - function nonces(address owner) external view returns (uint256); - - /** - * @dev Returns the domain separator used in the encoding of the signature for {permit}, as defined by {EIP712}. - */ - // solhint-disable-next-line func-name-mixedcase - function DOMAIN_SEPARATOR() external view returns (bytes32); -} - - - -/** - * @title SafeERC20 - * @dev Wrappers around ERC20 operations that throw on failure (when the token - * contract returns false). Tokens that return no value (and instead revert or - * throw on failure) are also supported, non-reverting calls are assumed to be - * successful. - * To use this library you can add a `using SafeERC20 for IERC20;` statement to your contract, - * which allows you to call the safe operations as `token.safeTransfer(...)`, etc. - */ -library SafeERC20 { - using Address for address; - - function safeTransfer( - IERC20 token, - address to, - uint256 value - ) internal { - _callOptionalReturn(token, abi.encodeWithSelector(token.transfer.selector, to, value)); - } - - function safeTransferFrom( - IERC20 token, - address from, - address to, - uint256 value - ) internal { - _callOptionalReturn(token, abi.encodeWithSelector(token.transferFrom.selector, from, to, value)); - } - - /** - * @dev Deprecated. This function has issues similar to the ones found in - * {IERC20-approve}, and its usage is discouraged. - * - * Whenever possible, use {safeIncreaseAllowance} and - * {safeDecreaseAllowance} instead. - */ - function safeApprove( - IERC20 token, - address spender, - uint256 value - ) internal { - // safeApprove should only be called when setting an initial allowance, - // or when resetting it to zero. To increase and decrease it, use - // 'safeIncreaseAllowance' and 'safeDecreaseAllowance' - require( - (value == 0) || (token.allowance(address(this), spender) == 0), - "SafeERC20: approve from non-zero to non-zero allowance" - ); - _callOptionalReturn(token, abi.encodeWithSelector(token.approve.selector, spender, value)); - } - - function safeIncreaseAllowance( - IERC20 token, - address spender, - uint256 value - ) internal { - uint256 newAllowance = token.allowance(address(this), spender) + value; - _callOptionalReturn(token, abi.encodeWithSelector(token.approve.selector, spender, newAllowance)); - } - - function safeDecreaseAllowance( - IERC20 token, - address spender, - uint256 value - ) internal { - unchecked { - uint256 oldAllowance = token.allowance(address(this), spender); - require(oldAllowance >= value, "SafeERC20: decreased allowance below zero"); - uint256 newAllowance = oldAllowance - value; - _callOptionalReturn(token, abi.encodeWithSelector(token.approve.selector, spender, newAllowance)); - } - } - - function safePermit( - IERC20Permit token, - address owner, - address spender, - uint256 value, - uint256 deadline, - uint8 v, - bytes32 r, - bytes32 s - ) internal { - uint256 nonceBefore = token.nonces(owner); - token.permit(owner, spender, value, deadline, v, r, s); - uint256 nonceAfter = token.nonces(owner); - require(nonceAfter == nonceBefore + 1, "SafeERC20: permit did not succeed"); - } - - /** - * @dev Imitates a Solidity high-level call (i.e. a regular function call to a contract), relaxing the requirement - * on the return value: the return value is optional (but if data is returned, it must not be false). - * @param token The token targeted by the call. - * @param data The call data (encoded using abi.encode or one of its variants). - */ - function _callOptionalReturn(IERC20 token, bytes memory data) private { - // We need to perform a low level call here, to bypass Solidity's return data size checking mechanism, since - // we're implementing it ourselves. We use {Address.functionCall} to perform this call, which verifies that - // the target address contains contract code and also asserts for success in the low-level call. - - bytes memory returndata = address(token).functionCall(data, "SafeERC20: low-level call failed"); - if (returndata.length > 0) { - // Return data is optional - require(abi.decode(returndata, (bool)), "SafeERC20: ERC20 operation did not succeed"); - } - } -} - - - - - - - - - - - - - - -/** - * @dev Provides information about the current execution context, including the - * sender of the transaction and its data. While these are generally available - * via msg.sender and msg.data, they should not be accessed in such a direct - * manner, since when dealing with meta-transactions the account sending and - * paying for execution may not be the actual sender (as far as an application - * is concerned). - * - * This contract is only required for intermediate, library-like contracts. - */ -abstract contract Context { - function _msgSender() internal view virtual returns (address) { - return msg.sender; - } - - function _msgData() internal view virtual returns (bytes calldata) { - return msg.data; - } -} - - -/** - * @dev Contract module which provides a basic access control mechanism, where - * there is an account (an owner) that can be granted exclusive access to - * specific functions. - * - * By default, the owner account will be the one that deploys the contract. This - * can later be changed with {transferOwnership}. - * - * This module is used through inheritance. It will make available the modifier - * `onlyOwner`, which can be applied to your functions to restrict their use to - * the owner. - */ -abstract contract Ownable is Context { - address private _owner; - - event OwnershipTransferred(address indexed previousOwner, address indexed newOwner); - - /** - * @dev Initializes the contract setting the deployer as the initial owner. - */ - constructor() { - _transferOwnership(_msgSender()); - } - - /** - * @dev Throws if called by any account other than the owner. - */ - modifier onlyOwner() { - _checkOwner(); - _; - } - - /** - * @dev Returns the address of the current owner. - */ - function owner() public view virtual returns (address) { - return _owner; - } - - /** - * @dev Throws if the sender is not the owner. - */ - function _checkOwner() internal view virtual { - require(owner() == _msgSender(), "Ownable: caller is not the owner"); - } - - /** - * @dev Leaves the contract without owner. It will not be possible to call - * `onlyOwner` functions anymore. Can only be called by the current owner. - * - * NOTE: Renouncing ownership will leave the contract without an owner, - * thereby removing any functionality that is only available to the owner. - */ - function renounceOwnership() public virtual onlyOwner { - _transferOwnership(address(0)); - } - - /** - * @dev Transfers ownership of the contract to a new account (`newOwner`). - * Can only be called by the current owner. - */ - function transferOwnership(address newOwner) public virtual onlyOwner { - require(newOwner != address(0), "Ownable: new owner is the zero address"); - _transferOwnership(newOwner); - } - - /** - * @dev Transfers ownership of the contract to a new account (`newOwner`). - * Internal function without access restriction. - */ - function _transferOwnership(address newOwner) internal virtual { - address oldOwner = _owner; - _owner = newOwner; - emit OwnershipTransferred(oldOwner, newOwner); - } -} - - -contract Operator is Ownable { - address public operator; - uint256 constant baseRate = 10000; - - modifier onlyOperator { - require(msg.sender == owner() || msg.sender == operator, "no permission"); - _; - } - - function setOperator(address operator_) external onlyOwner { - operator = operator_; - } - - - function getCurrTime() external view returns(uint256) { - return block.timestamp; - } - - function getBlockNum() external view returns(uint256) { - return block.number; - } - -} - - - - - -/** - * @dev Library for managing - * https://en.wikipedia.org/wiki/Set_(abstract_data_type)[sets] of primitive - * types. - * - * Sets have the following properties: - * - * - Elements are added, removed, and checked for existence in constant time - * (O(1)). - * - Elements are enumerated in O(n). No guarantees are made on the ordering. - * - * ``` - * contract Example { - * // Add the library methods - * using EnumerableSet for EnumerableSet.AddressSet; - * - * // Declare a set state variable - * EnumerableSet.AddressSet private mySet; - * } - * ``` - * - * As of v3.3.0, sets of type `bytes32` (`Bytes32Set`), `address` (`AddressSet`) - * and `uint256` (`UintSet`) are supported. - * - * [WARNING] - * ==== - * Trying to delete such a structure from storage will likely result in data corruption, rendering the structure unusable. - * See https://github.com/ethereum/solidity/pull/11843[ethereum/solidity#11843] for more info. - * - * In order to clean an EnumerableSet, you can either remove all elements one by one or create a fresh instance using an array of EnumerableSet. - * ==== - */ - -library EnumerableSet { - // To implement this library for multiple types with as little code - // repetition as possible, we write it in terms of a generic Set type with - // bytes32 values. - // The Set implementation uses private functions, and user-facing - // implementations (such as AddressSet) are just wrappers around the - // underlying Set. - // This means that we can only create new EnumerableSets for types that fit - // in bytes32. - - struct Set { - // Storage of set values - bytes32[] _values; - // Position of the value in the `values` array, plus 1 because index 0 - // means a value is not in the set. - mapping(bytes32 => uint256) _indexes; - } - - /** - * @dev Add a value to a set. O(1). - * - * Returns true if the value was added to the set, that is if it was not - * already present. - */ - function _add(Set storage set, bytes32 value) private returns (bool) { - if (!_contains(set, value)) { - set._values.push(value); - // The value is stored at length-1, but we add 1 to all indexes - // and use 0 as a sentinel value - set._indexes[value] = set._values.length; - return true; - } else { - return false; - } - } - - /** - * @dev Removes a value from a set. O(1). - * - * Returns true if the value was removed from the set, that is if it was - * present. - */ - function _remove(Set storage set, bytes32 value) private returns (bool) { - // We read and store the value's index to prevent multiple reads from the same storage slot - uint256 valueIndex = set._indexes[value]; - - if (valueIndex != 0) { - // Equivalent to contains(set, value) - // To delete an element from the _values array in O(1), we swap the element to delete with the last one in - // the array, and then remove the last element (sometimes called as 'swap and pop'). - // This modifies the order of the array, as noted in {at}. - - uint256 toDeleteIndex = valueIndex - 1; - uint256 lastIndex = set._values.length - 1; - - if (lastIndex != toDeleteIndex) { - bytes32 lastValue = set._values[lastIndex]; - - // Move the last value to the index where the value to delete is - set._values[toDeleteIndex] = lastValue; - // Update the index for the moved value - set._indexes[lastValue] = valueIndex; // Replace lastValue's index to valueIndex - } - - // Delete the slot where the moved value was stored - set._values.pop(); - - // Delete the index for the deleted slot - delete set._indexes[value]; - - return true; - } else { - return false; - } - } - - /** - * @dev Returns true if the value is in the set. O(1). - */ - function _contains(Set storage set, bytes32 value) private view returns (bool) { - return set._indexes[value] != 0; - } - - /** - * @dev Returns the number of values on the set. O(1). - */ - function _length(Set storage set) private view returns (uint256) { - return set._values.length; - } - - /** - * @dev Returns the value stored at position `index` in the set. O(1). - * - * Note that there are no guarantees on the ordering of values inside the - * array, and it may change when more values are added or removed. - * - * Requirements: - * - * - `index` must be strictly less than {length}. - */ - function _at(Set storage set, uint256 index) private view returns (bytes32) { - return set._values[index]; - } - - /** - * @dev Return the entire set in an array - * - * WARNING: This operation will copy the entire storage to memory, which can be quite expensive. This is designed - * to mostly be used by view accessors that are queried without any gas fees. Developers should keep in mind that - * this function has an unbounded cost, and using it as part of a state-changing function may render the function - * uncallable if the set grows to a point where copying to memory consumes too much gas to fit in a block. - */ - function _values(Set storage set) private view returns (bytes32[] memory) { - return set._values; - } - - // Bytes32Set - - struct Bytes32Set { - Set _inner; - } - - /** - * @dev Add a value to a set. O(1). - * - * Returns true if the value was added to the set, that is if it was not - * already present. - */ - function add(Bytes32Set storage set, bytes32 value) internal returns (bool) { - return _add(set._inner, value); - } - - /** - * @dev Removes a value from a set. O(1). - * - * Returns true if the value was removed from the set, that is if it was - * present. - */ - function remove(Bytes32Set storage set, bytes32 value) internal returns (bool) { - return _remove(set._inner, value); - } - - /** - * @dev Returns true if the value is in the set. O(1). - */ - function contains(Bytes32Set storage set, bytes32 value) internal view returns (bool) { - return _contains(set._inner, value); - } - - /** - * @dev Returns the number of values in the set. O(1). - */ - function length(Bytes32Set storage set) internal view returns (uint256) { - return _length(set._inner); - } - - /** - * @dev Returns the value stored at position `index` in the set. O(1). - * - * Note that there are no guarantees on the ordering of values inside the - * array, and it may change when more values are added or removed. - * - * Requirements: - * - * - `index` must be strictly less than {length}. - */ - function at(Bytes32Set storage set, uint256 index) internal view returns (bytes32) { - return _at(set._inner, index); - } - - /** - * @dev Return the entire set in an array - * - * WARNING: This operation will copy the entire storage to memory, which can be quite expensive. This is designed - * to mostly be used by view accessors that are queried without any gas fees. Developers should keep in mind that - * this function has an unbounded cost, and using it as part of a state-changing function may render the function - * uncallable if the set grows to a point where copying to memory consumes too much gas to fit in a block. - */ - function values(Bytes32Set storage set) internal view returns (bytes32[] memory) { - return _values(set._inner); - } - - // AddressSet - - struct AddressSet { - Set _inner; - } - - /** - * @dev Add a value to a set. O(1). - * - * Returns true if the value was added to the set, that is if it was not - * already present. - */ - function add(AddressSet storage set, address value) internal returns (bool) { - return _add(set._inner, bytes32(uint256(uint160(value)))); - } - - /** - * @dev Removes a value from a set. O(1). - * - * Returns true if the value was removed from the set, that is if it was - * present. - */ - function remove(AddressSet storage set, address value) internal returns (bool) { - return _remove(set._inner, bytes32(uint256(uint160(value)))); - } - - /** - * @dev Returns true if the value is in the set. O(1). - */ - function contains(AddressSet storage set, address value) internal view returns (bool) { - return _contains(set._inner, bytes32(uint256(uint160(value)))); - } - - /** - * @dev Returns the number of values in the set. O(1). - */ - function length(AddressSet storage set) internal view returns (uint256) { - return _length(set._inner); - } - - /** - * @dev Returns the value stored at position `index` in the set. O(1). - * - * Note that there are no guarantees on the ordering of values inside the - * array, and it may change when more values are added or removed. - * - * Requirements: - * - * - `index` must be strictly less than {length}. - */ - function at(AddressSet storage set, uint256 index) internal view returns (address) { - return address(uint160(uint256(_at(set._inner, index)))); - } - - /** - * @dev Return the entire set in an array - * - * WARNING: This operation will copy the entire storage to memory, which can be quite expensive. This is designed - * to mostly be used by view accessors that are queried without any gas fees. Developers should keep in mind that - * this function has an unbounded cost, and using it as part of a state-changing function may render the function - * uncallable if the set grows to a point where copying to memory consumes too much gas to fit in a block. - */ - function values(AddressSet storage set) internal view returns (address[] memory) { - bytes32[] memory store = _values(set._inner); - address[] memory result; - - /// @solidity memory-safe-assembly - assembly { - result := store - } - - return result; - } - - // UintSet - - struct UintSet { - Set _inner; - } - - /** - * @dev Add a value to a set. O(1). - * - * Returns true if the value was added to the set, that is if it was not - * already present. - */ - function add(UintSet storage set, uint256 value) internal returns (bool) { - return _add(set._inner, bytes32(value)); - } - - /** - * @dev Removes a value from a set. O(1). - * - * Returns true if the value was removed from the set, that is if it was - * present. - */ - function remove(UintSet storage set, uint256 value) internal returns (bool) { - return _remove(set._inner, bytes32(value)); - } - - /** - * @dev Returns true if the value is in the set. O(1). - */ - function contains(UintSet storage set, uint256 value) internal view returns (bool) { - return _contains(set._inner, bytes32(value)); - } - - /** - * @dev Returns the number of values on the set. O(1). - */ - function length(UintSet storage set) internal view returns (uint256) { - return _length(set._inner); - } - - /** - * @dev Returns the value stored at position `index` in the set. O(1). - * - * Note that there are no guarantees on the ordering of values inside the - * array, and it may change when more values are added or removed. - * - * Requirements: - * - * - `index` must be strictly less than {length}. - */ - function at(UintSet storage set, uint256 index) internal view returns (uint256) { - return uint256(_at(set._inner, index)); - } - - /** - * @dev Return the entire set in an array - * - * WARNING: This operation will copy the entire storage to memory, which can be quite expensive. This is designed - * to mostly be used by view accessors that are queried without any gas fees. Developers should keep in mind that - * this function has an unbounded cost, and using it as part of a state-changing function may render the function - * uncallable if the set grows to a point where copying to memory consumes too much gas to fit in a block. - */ - function values(UintSet storage set) internal view returns (uint256[] memory) { - bytes32[] memory store = _values(set._inner); - uint256[] memory result; - - /// @solidity memory-safe-assembly - assembly { - result := store - } - - return result; - } -} - - -contract ActivityPool is Operator { - using SafeMath for uint256; - using SafeERC20 for IERC20; - using EnumerableSet for EnumerableSet.AddressSet; - using EnumerableSet for EnumerableSet.UintSet; - - event AddNewAct(uint256 id); - event Bet(address user, uint256 pID, uint256 bType, uint256 amount, uint256 time); - event SetPrize(uint256 pID, uint256 bType); - event Claim(address user, uint256 pID, uint256 bType, uint256 amount); - event RemovePeriodAct(uint256 pID); - - uint256 public constant muti = 1e18; - uint256 public periodID; - uint256 public betID; - - struct UserInfo { - address user; - uint256 pID; - uint256 amount; - uint256 betTime; - uint256 bType; - uint256 claimAmount; - } - - struct ActInfo { - string name; - string aName; - string bName; - address rewardToken; - uint256 startTime; - uint256 endTime; - uint256 minAmount; - uint256 maxAmount; - uint256 aAmount; - uint256 bAmount; - uint256 winType; - bool isBet; - } - - struct TimeInfo { - uint256 time; - uint256 aAmount; - uint256 bAmount; - } - - struct BestInfo { - address aUser; - address bUser; - uint256 aBet; - uint256 bBet; - } - - mapping(uint256 => BestInfo) bestInfo; - mapping(uint256 => uint256) public timeID; - mapping(uint256 => mapping(uint256 => TimeInfo)) public timeInfo; - mapping(address => mapping(uint256 => uint256)) public userBet; - mapping(uint256 => UserInfo) public betInfo; - mapping(uint256 => uint256) public perAmount; - mapping(uint256 => ActInfo) public actInfo; - mapping(uint256 => mapping(uint256 => string)) public descripName; - - mapping(address => EnumerableSet.UintSet) userPid; - mapping(uint256 => EnumerableSet.AddressSet) aUsers; - mapping(uint256 => EnumerableSet.AddressSet) bUsers; - EnumerableSet.UintSet activePeriod; - EnumerableSet.UintSet removePeriod; - - function addNewAct( - string memory name, - string memory aName, - string memory bName, - address token, - uint256 startTime, - uint256 endTime, - uint256 minAmount, - uint256 maxAmount - ) external onlyOperator { - - checkAdd(msg.sender, startTime, endTime, minAmount, maxAmount); - uint256 id = ++periodID; - actInfo[id].name = name; - actInfo[id].aName = aName; - actInfo[id].bName = bName; - actInfo[id].startTime = startTime; - actInfo[id].endTime = endTime; - actInfo[id].minAmount = minAmount; - actInfo[id].maxAmount = maxAmount; - actInfo[id].rewardToken = token; - descripName[id][1] = aName; - descripName[id][2] = bName; - activePeriod.add(id); - - emit AddNewAct(id); - } - - - function removePeriodAct(uint256 pID) external onlyOperator { - checkRemove(pID); - - activePeriod.remove(pID); - removePeriod.add(pID); - - emit RemovePeriodAct(pID); - } - - - function bet(uint256 pID, uint256 bType, uint256 amount) external payable { - checkBet(msg.sender, pID, bType, amount); - if(actInfo[pID].rewardToken == address(0)) { - require(msg.value == amount, "value err"); - } else { - require(msg.value == 0, "value amount err"); - } - - if(bType == 1) { - if(amount > bestInfo[pID].aBet) { - bestInfo[pID].aUser = msg.sender; - bestInfo[pID].aBet = amount; - } - } else { - if(amount > bestInfo[pID].bBet) { - bestInfo[pID].bUser = msg.sender; - bestInfo[pID].bBet = amount; - } - } - - userPid[msg.sender].add(pID); - uint256 id = ++betID; - userBet[msg.sender][pID] = id; - - if(bType == 1) { - aUsers[pID].add(msg.sender); - actInfo[pID].aAmount = actInfo[pID].aAmount.add(amount); - } else { - bUsers[pID].add(msg.sender); - actInfo[pID].bAmount = actInfo[pID].bAmount.add(amount); - } - - actInfo[pID].isBet = true; - betInfo[id].user = msg.sender; - betInfo[id].pID = pID; - betInfo[id].amount = amount; - betInfo[id].betTime = block.timestamp; - betInfo[id].bType = bType; - - uint256 tID = ++timeID[pID]; - timeInfo[pID][tID].time = block.timestamp; - timeInfo[pID][tID].aAmount = actInfo[pID].aAmount; - timeInfo[pID][tID].bAmount = actInfo[pID].bAmount; - - if(actInfo[pID].rewardToken != address(0)) { - IERC20(actInfo[pID].rewardToken).safeTransferFrom(msg.sender, address(this), amount); - } - emit Bet(msg.sender, pID, bType, amount, betInfo[id].betTime); - } - - function setPrize(uint256 pID, uint256 bType) external onlyOperator { - checkSetPrize(msg.sender, pID, bType); - - if(block.timestamp <= actInfo[pID].startTime) { - actInfo[pID].startTime = block.timestamp; - - } - actInfo[pID].endTime = block.timestamp; - - actInfo[pID].winType = bType; - perAmount[pID] = getPerAmount(pID, bType); - - emit SetPrize(pID, bType); - } - - function recive() public payable {} - - function claim(uint256 pID) external { - uint256 amount = checkClaim(msg.sender, pID); - - uint256 id = userBet[msg.sender][pID]; - betInfo[id].claimAmount = amount; - if(actInfo[pID].rewardToken != address(0)) { - IERC20(actInfo[pID].rewardToken).safeTransfer(msg.sender, amount); - } else { - payable(msg.sender).transfer(amount); - } - - emit Claim(msg.sender, pID, betInfo[id].bType, amount); - } - - function checkClaim(address user, uint256 pID) public view returns(uint256 amount) { - require(userPid[user].contains(pID), "not bet"); - uint256 id = userBet[user][pID]; - require(betInfo[id].user == user, "not user"); - require(actInfo[pID].winType != 0, "not prize"); - require(betInfo[id].claimAmount == 0, "has claim"); - - if(actInfo[pID].winType != 3) { - require(actInfo[pID].winType == betInfo[id].bType, "not right"); - amount = perAmount[pID].mul(betInfo[id].amount).div(muti); - require(amount > 0, "no amount"); - } else { - amount = betInfo[id].amount; - } - - return amount; - } - - function getActualRate( - address user, - uint256 pID, - uint256 bType, - uint256 amount - ) external view returns(uint256, uint256, bool) { - if(bType < 1 || bType > 2 || !activePeriod.contains(pID)) { - return (0, 0, false); - } else if(userBet[user][pID] != 0 || actInfo[pID].winType != 0 || amount == 0) { - (uint256 ra, uint256 rb) = getRate(pID, timeID[pID]); - return (ra, rb, false); - } else { - (uint256 aAmount, uint256 bAmount) = (actInfo[pID].aAmount, actInfo[pID].bAmount); - if(bType == 1) { - aAmount = aAmount.add(amount); - } else { - bAmount = bAmount.add(amount); - } - - uint256 total = aAmount.add(bAmount); - if(bAmount == 0 && aAmount != 0) { - return (muti, 0, true); - } - if(bAmount != 0 && aAmount == 0) { - return (0, muti, true); - } - return (total.mul(muti).div(aAmount), total.mul(muti).div(bAmount), true); - } - } - - function getRate(uint256 pID, uint256 tID) public view returns(uint256, uint256) { - (uint256 aAmount, uint256 bAmount) = (timeInfo[pID][tID].aAmount, timeInfo[pID][tID].bAmount); - uint256 total = aAmount.add(bAmount); - if(total == 0) { - return (0, 0); - } - if(bAmount == 0 && aAmount != 0) { - return (muti, 0); - } - if(bAmount != 0 && aAmount == 0) { - return (0, muti); - } - return (total.mul(muti).div(aAmount), total.mul(muti).div(bAmount)); - } - - function getBestInfo(uint256 pID) - external - view - returns(address aUser, address bUser, uint256 aBet, uint256 bBet, uint256 aReward, uint256 bReward) - { - aUser = bestInfo[pID].aUser; - bUser = bestInfo[pID].bUser; - aBet = bestInfo[pID].aBet; - bBet = bestInfo[pID].bBet; - aReward = getPerAmount(pID, 1).mul(aBet).div(muti); - bReward = getPerAmount(pID, 2).mul(bBet).div(muti); - } - - function getPerAmount(uint256 pID, uint256 bType) public view returns(uint256) { - uint256 total = actInfo[pID].aAmount.add(actInfo[pID].bAmount); - if(total == 0) { - return 0; - } - - if(actInfo[pID].winType == 3) { - return muti; - } - - if(bType == 1) { - if(actInfo[pID].aAmount == 0 || actInfo[pID].winType == 2) { - return 0; - } - return total.mul(muti).div(actInfo[pID].aAmount); - } - - if(bType == 2) { - if(actInfo[pID].bAmount == 0 || actInfo[pID].winType == 1) { - return 0; - } - return total.mul(muti).div(actInfo[pID].bAmount); - } - - return 0; - - } - - function checkSetPrize(address user, uint256 pID, uint256 bType) public view returns(bool) { - require(user == owner() || user == operator, "no permission"); - require(bType > 0 && bType <= 3, "type err"); - require(activePeriod.contains(pID), "not active"); - require(actInfo[pID].winType == 0, "has set"); - - return true; - } - - function checkBet( - address user, - uint256 pID, - uint256 bType, - uint256 amount - ) public view returns(bool) { - require(activePeriod.contains(pID), "not active"); - require(actInfo[pID].startTime <= block.timestamp, "not start"); - require(actInfo[pID].endTime > block.timestamp, "has end"); - require(!userPid[user].contains(pID), "has bet"); - require(bType > 0 && bType < 3, "type err"); - require(amount >= actInfo[pID].minAmount && amount <= actInfo[pID].maxAmount, "amount err"); - if(actInfo[pID].rewardToken != address(0)) { - require(IERC20(actInfo[pID].rewardToken).allowance(user, address(this)) >= amount, "not approve enough"); - require(IERC20(actInfo[pID].rewardToken).balanceOf(user) >= amount, "not enough"); - } else { - require(user.balance >= amount, "main token err"); - } - - return true; - } - - - function checkRemove(uint256 pID) public view returns(bool) { - require(activePeriod.contains(pID), "not in"); - require(!actInfo[pID].isBet, "has bet"); - - return true; - } - - function checkAdd( - address user, - uint256 startTime, - uint256 endTime, - uint256 minAmount, - uint256 maxAmount - ) public view returns(bool) { - require(user == owner() || user == operator, "no permission"); - require(startTime > block.timestamp, "startTime err"); - require(endTime > startTime, "endTime err"); - require(minAmount > 0 && maxAmount > minAmount, "amount err"); - - return true; - } - - function getStatus(uint256 pID) external view returns(uint256) { - if(!removePeriod.contains(pID) && !activePeriod.contains(pID)) { - return 5; - } else if(removePeriod.contains(pID)) { - return 6; - } else if(block.timestamp < actInfo[pID].startTime) { - return 1; - } else if ( - actInfo[pID].startTime <= block.timestamp && - actInfo[pID].endTime > block.timestamp - ) { - return 2; - } else if (actInfo[pID].endTime <= block.timestamp && actInfo[pID].winType == 0){ - return 3; - } else if(actInfo[pID].winType != 0) { - return 4; - } - return 0; - } - - function getUserPidNum(address user) external view returns(uint256) { - return userPid[user].length(); - } - - function getUserPid(address user, uint256 index) external view returns(uint256) { - return userPid[user].at(index); - } - - function getAUsersNum(uint256 pID) external view returns(uint256) { - return aUsers[pID].length(); - } - - function getAUsers(uint256 pID, uint256 index) external view returns(address) { - return aUsers[pID].at(index); - } - - function getBUsersNum(uint256 pID) external view returns(uint256) { - return bUsers[pID].length(); - } - - function getBUsers(uint256 pID, uint256 index) external view returns(address) { - return bUsers[pID].at(index); - } - - function getActivePeriodNum() external view returns(uint256) { - return activePeriod.length(); - } - - function getActivePeriod(uint256 index) external view returns(uint256) { - return activePeriod.at(index); - } - - function getRemovePeriodNum() external view returns(uint256) { - return removePeriod.length(); - } - - function getRemovePeriod(uint256 index) external view returns(uint256) { - return removePeriod.at(index); - } -} \ No newline at end of file diff --git a/app/api/uploads/ActivityPool-1729821993926-279009626.sol b/app/api/uploads/ActivityPool-1729821993926-279009626.sol deleted file mode 100644 index daf3372..0000000 --- a/app/api/uploads/ActivityPool-1729821993926-279009626.sol +++ /dev/null @@ -1,1648 +0,0 @@ -// SPDX-License-Identifier: MIT -// OpenZeppelin Contracts (last updated v4.7.0) (utils/Address.sol) - -pragma solidity ^0.8.1; - -/** - * @dev Collection of functions related to the address type - */ -library Address { - /** - * @dev Returns true if `account` is a contract. - * - * [IMPORTANT] - * ==== - * It is unsafe to assume that an address for which this function returns - * false is an externally-owned account (EOA) and not a contract. - * - * Among others, `isContract` will return false for the following - * types of addresses: - * - * - an externally-owned account - * - a contract in construction - * - an address where a contract will be created - * - an address where a contract lived, but was destroyed - * ==== - * - * [IMPORTANT] - * ==== - * You shouldn't rely on `isContract` to protect against flash loan attacks! - * - * Preventing calls from contracts is highly discouraged. It breaks composability, breaks support for smart wallets - * like Gnosis Safe, and does not provide security since it can be circumvented by calling from a contract - * constructor. - * ==== - */ - function isContract(address account) internal view returns (bool) { - // This method relies on extcodesize/address.code.length, which returns 0 - // for contracts in construction, since the code is only stored at the end - // of the constructor execution. - - return account.code.length > 0; - } - - /** - * @dev Replacement for Solidity's `transfer`: sends `amount` wei to - * `recipient`, forwarding all available gas and reverting on errors. - * - * https://eips.ethereum.org/EIPS/eip-1884[EIP1884] increases the gas cost - * of certain opcodes, possibly making contracts go over the 2300 gas limit - * imposed by `transfer`, making them unable to receive funds via - * `transfer`. {sendValue} removes this limitation. - * - * https://diligence.consensys.net/posts/2019/09/stop-using-soliditys-transfer-now/[Learn more]. - * - * IMPORTANT: because control is transferred to `recipient`, care must be - * taken to not create reentrancy vulnerabilities. Consider using - * {ReentrancyGuard} or the - * https://solidity.readthedocs.io/en/v0.5.11/security-considerations.html#use-the-checks-effects-interactions-pattern[checks-effects-interactions pattern]. - */ - function sendValue(address payable recipient, uint256 amount) internal { - require(address(this).balance >= amount, "Address: insufficient balance"); - - (bool success, ) = recipient.call{value: amount}(""); - require(success, "Address: unable to send value, recipient may have reverted"); - } - - /** - * @dev Performs a Solidity function call using a low level `call`. A - * plain `call` is an unsafe replacement for a function call: use this - * function instead. - * - * If `target` reverts with a revert reason, it is bubbled up by this - * function (like regular Solidity function calls). - * - * Returns the raw returned data. To convert to the expected return value, - * use https://solidity.readthedocs.io/en/latest/units-and-global-variables.html?highlight=abi.decode#abi-encoding-and-decoding-functions[`abi.decode`]. - * - * Requirements: - * - * - `target` must be a contract. - * - calling `target` with `data` must not revert. - * - * _Available since v3.1._ - */ - function functionCall(address target, bytes memory data) internal returns (bytes memory) { - return functionCallWithValue(target, data, 0, "Address: low-level call failed"); - } - - /** - * @dev Same as {xref-Address-functionCall-address-bytes-}[`functionCall`], but with - * `errorMessage` as a fallback revert reason when `target` reverts. - * - * _Available since v3.1._ - */ - function functionCall( - address target, - bytes memory data, - string memory errorMessage - ) internal returns (bytes memory) { - return functionCallWithValue(target, data, 0, errorMessage); - } - - /** - * @dev Same as {xref-Address-functionCall-address-bytes-}[`functionCall`], - * but also transferring `value` wei to `target`. - * - * Requirements: - * - * - the calling contract must have an ETH balance of at least `value`. - * - the called Solidity function must be `payable`. - * - * _Available since v3.1._ - */ - function functionCallWithValue( - address target, - bytes memory data, - uint256 value - ) internal returns (bytes memory) { - return functionCallWithValue(target, data, value, "Address: low-level call with value failed"); - } - - /** - * @dev Same as {xref-Address-functionCallWithValue-address-bytes-uint256-}[`functionCallWithValue`], but - * with `errorMessage` as a fallback revert reason when `target` reverts. - * - * _Available since v3.1._ - */ - function functionCallWithValue( - address target, - bytes memory data, - uint256 value, - string memory errorMessage - ) internal returns (bytes memory) { - require(address(this).balance >= value, "Address: insufficient balance for call"); - (bool success, bytes memory returndata) = target.call{value: value}(data); - return verifyCallResultFromTarget(target, success, returndata, errorMessage); - } - - /** - * @dev Same as {xref-Address-functionCall-address-bytes-}[`functionCall`], - * but performing a static call. - * - * _Available since v3.3._ - */ - function functionStaticCall(address target, bytes memory data) internal view returns (bytes memory) { - return functionStaticCall(target, data, "Address: low-level static call failed"); - } - - /** - * @dev Same as {xref-Address-functionCall-address-bytes-string-}[`functionCall`], - * but performing a static call. - * - * _Available since v3.3._ - */ - function functionStaticCall( - address target, - bytes memory data, - string memory errorMessage - ) internal view returns (bytes memory) { - (bool success, bytes memory returndata) = target.staticcall(data); - return verifyCallResultFromTarget(target, success, returndata, errorMessage); - } - - /** - * @dev Same as {xref-Address-functionCall-address-bytes-}[`functionCall`], - * but performing a delegate call. - * - * _Available since v3.4._ - */ - function functionDelegateCall(address target, bytes memory data) internal returns (bytes memory) { - return functionDelegateCall(target, data, "Address: low-level delegate call failed"); - } - - /** - * @dev Same as {xref-Address-functionCall-address-bytes-string-}[`functionCall`], - * but performing a delegate call. - * - * _Available since v3.4._ - */ - function functionDelegateCall( - address target, - bytes memory data, - string memory errorMessage - ) internal returns (bytes memory) { - (bool success, bytes memory returndata) = target.delegatecall(data); - return verifyCallResultFromTarget(target, success, returndata, errorMessage); - } - - /** - * @dev Tool to verify that a low level call to smart-contract was successful, and revert (either by bubbling - * the revert reason or using the provided one) in case of unsuccessful call or if target was not a contract. - * - * _Available since v4.8._ - */ - function verifyCallResultFromTarget( - address target, - bool success, - bytes memory returndata, - string memory errorMessage - ) internal view returns (bytes memory) { - if (success) { - if (returndata.length == 0) { - // only check isContract if the call was successful and the return data is empty - // otherwise we already know that it was a contract - require(isContract(target), "Address: call to non-contract"); - } - return returndata; - } else { - _revert(returndata, errorMessage); - } - } - - /** - * @dev Tool to verify that a low level call was successful, and revert if it wasn't, either by bubbling the - * revert reason or using the provided one. - * - * _Available since v4.3._ - */ - function verifyCallResult( - bool success, - bytes memory returndata, - string memory errorMessage - ) internal pure returns (bytes memory) { - if (success) { - return returndata; - } else { - _revert(returndata, errorMessage); - } - } - - function _revert(bytes memory returndata, string memory errorMessage) private pure { - // Look for revert reason and bubble it up if present - if (returndata.length > 0) { - // The easiest way to bubble the revert reason is using memory via assembly - /// @solidity memory-safe-assembly - assembly { - let returndata_size := mload(returndata) - revert(add(32, returndata), returndata_size) - } - } else { - revert(errorMessage); - } - } -} - -// OpenZeppelin Contracts (last updated v4.6.0) (token/ERC20/IERC20.sol) - - - -/** - * @dev Interface of the ERC20 standard as defined in the EIP. - */ -interface IERC20 { - /** - * @dev Emitted when `value` tokens are moved from one account (`from`) to - * another (`to`). - * - * Note that `value` may be zero. - */ - event Transfer(address indexed from, address indexed to, uint256 value); - - /** - * @dev Emitted when the allowance of a `spender` for an `owner` is set by - * a call to {approve}. `value` is the new allowance. - */ - event Approval(address indexed owner, address indexed spender, uint256 value); - - /** - * @dev Returns the amount of tokens in existence. - */ - function totalSupply() external view returns (uint256); - - /** - * @dev Returns the amount of tokens owned by `account`. - */ - function balanceOf(address account) external view returns (uint256); - - /** - * @dev Moves `amount` tokens from the caller's account to `to`. - * - * Returns a boolean value indicating whether the operation succeeded. - * - * Emits a {Transfer} event. - */ - function transfer(address to, uint256 amount) external returns (bool); - - /** - * @dev Returns the remaining number of tokens that `spender` will be - * allowed to spend on behalf of `owner` through {transferFrom}. This is - * zero by default. - * - * This value changes when {approve} or {transferFrom} are called. - */ - function allowance(address owner, address spender) external view returns (uint256); - - /** - * @dev Sets `amount` as the allowance of `spender` over the caller's tokens. - * - * Returns a boolean value indicating whether the operation succeeded. - * - * IMPORTANT: Beware that changing an allowance with this method brings the risk - * that someone may use both the old and the new allowance by unfortunate - * transaction ordering. One possible solution to mitigate this race - * condition is to first reduce the spender's allowance to 0 and set the - * desired value afterwards: - * https://github.com/ethereum/EIPs/issues/20#issuecomment-263524729 - * - * Emits an {Approval} event. - */ - function approve(address spender, uint256 amount) external returns (bool); - - /** - * @dev Moves `amount` tokens from `from` to `to` using the - * allowance mechanism. `amount` is then deducted from the caller's - * allowance. - * - * Returns a boolean value indicating whether the operation succeeded. - * - * Emits a {Transfer} event. - */ - function transferFrom( - address from, - address to, - uint256 amount - ) external returns (bool); - - - function mint(address account_, uint256 amount_) external; - - function burn(uint256 amount) external; - -} - - - - - - - - - - - -/** - * @dev Wrappers over Solidity's arithmetic operations with added overflow - * checks. - * - * Arithmetic operations in Solidity wrap on overflow. This can easily result - * in bugs, because programmers usually assume that an overflow raises an - * error, which is the standard behavior in high level programming languages. - * `SafeMath` restores this intuition by reverting the transaction when an - * operation overflows. - * - * Using this library instead of the unchecked operations eliminates an entire - * class of bugs, so it's recommended to use it always. - */ -library SafeMath { - /** - * @dev Returns the addition of two unsigned integers, reverting on - * overflow. - * - * Counterpart to Solidity's `+` operator. - * - * Requirements: - * - * - Addition cannot overflow. - */ - function add(uint256 a, uint256 b) internal pure returns (uint256) { - uint256 c = a + b; - require(c >= a, "SafeMath: addition overflow"); - - return c; - } - - /** - * @dev Returns the subtraction of two unsigned integers, reverting on - * overflow (when the result is negative). - * - * Counterpart to Solidity's `-` operator. - * - * Requirements: - * - * - Subtraction cannot overflow. - */ - function sub(uint256 a, uint256 b) internal pure returns (uint256) { - return sub(a, b, "SafeMath: subtraction overflow"); - } - - /** - * @dev Returns the subtraction of two unsigned integers, reverting with custom message on - * overflow (when the result is negative). - * - * Counterpart to Solidity's `-` operator. - * - * Requirements: - * - * - Subtraction cannot overflow. - */ - function sub( - uint256 a, - uint256 b, - string memory errorMessage - ) internal pure returns (uint256) { - require(b <= a, errorMessage); - uint256 c = a - b; - - return c; - } - - /** - * @dev Returns the multiplication of two unsigned integers, reverting on - * overflow. - * - * Counterpart to Solidity's `*` operator. - * - * Requirements: - * - * - Multiplication cannot overflow. - */ - function mul(uint256 a, uint256 b) internal pure returns (uint256) { - // Gas optimization: this is cheaper than requiring 'a' not being zero, but the - // benefit is lost if 'b' is also tested. - // See: https://github.com/OpenZeppelin/openzeppelin-contracts/pull/522 - if (a == 0) { - return 0; - } - - uint256 c = a * b; - require(c / a == b, "SafeMath: multiplication overflow"); - - return c; - } - - /** - * @dev Returns the integer division of two unsigned integers. Reverts on - * division by zero. The result is rounded towards zero. - * - * Counterpart to Solidity's `/` operator. Note: this function uses a - * `revert` opcode (which leaves remaining gas untouched) while Solidity - * uses an invalid opcode to revert (consuming all remaining gas). - * - * Requirements: - * - * - The divisor cannot be zero. - */ - function div(uint256 a, uint256 b) internal pure returns (uint256) { - return div(a, b, "SafeMath: division by zero"); - } - - /** - * @dev Returns the integer division of two unsigned integers. Reverts with custom message on - * division by zero. The result is rounded towards zero. - * - * Counterpart to Solidity's `/` operator. Note: this function uses a - * `revert` opcode (which leaves remaining gas untouched) while Solidity - * uses an invalid opcode to revert (consuming all remaining gas). - * - * Requirements: - * - * - The divisor cannot be zero. - */ - function div( - uint256 a, - uint256 b, - string memory errorMessage - ) internal pure returns (uint256) { - require(b > 0, errorMessage); - uint256 c = a / b; - // assert(a == b * c + a % b); // There is no case in which this doesn't hold - - return c; - } - - /** - * @dev Returns the remainder of dividing two unsigned integers. (unsigned integer modulo), - * Reverts when dividing by zero. - * - * Counterpart to Solidity's `%` operator. This function uses a `revert` - * opcode (which leaves remaining gas untouched) while Solidity uses an - * invalid opcode to revert (consuming all remaining gas). - * - * Requirements: - * - * - The divisor cannot be zero. - */ - function mod(uint256 a, uint256 b) internal pure returns (uint256) { - return mod(a, b, "SafeMath: modulo by zero"); - } - - /** - * @dev Returns the remainder of dividing two unsigned integers. (unsigned integer modulo), - * Reverts with custom message when dividing by zero. - * - * Counterpart to Solidity's `%` operator. This function uses a `revert` - * opcode (which leaves remaining gas untouched) while Solidity uses an - * invalid opcode to revert (consuming all remaining gas). - * - * Requirements: - * - * - The divisor cannot be zero. - */ - function mod( - uint256 a, - uint256 b, - string memory errorMessage - ) internal pure returns (uint256) { - require(b != 0, errorMessage); - return a % b; - } - - // babylonian method (https://en.wikipedia.org/wiki/Methods_of_computing_square_roots#Babylonian_method) - function sqrrt(uint256 a) internal pure returns (uint256 c) { - if (a > 3) { - c = a; - uint256 b = add(div(a, 2), 1); - while (b < c) { - c = b; - b = div(add(div(a, b), b), 2); - } - } else if (a != 0) { - c = 1; - } - } - - /* - * Expects percentage to be trailed by 00, - */ - function percentageAmount(uint256 total_, uint8 percentage_) internal pure returns (uint256 percentAmount_) { - return div(mul(total_, percentage_), 1000); - } - - /* - * Expects percentage to be trailed by 00, - */ - function substractPercentage(uint256 total_, uint8 percentageToSub_) internal pure returns (uint256 result_) { - return sub(total_, div(mul(total_, percentageToSub_), 1000)); - } - - function percentageOfTotal(uint256 part_, uint256 total_) internal pure returns (uint256 percent_) { - return div(mul(part_, 100), total_); - } - - /** - * Taken from Hypersonic https://github.com/M2629/HyperSonic/blob/main/Math.sol - * @dev Returns the average of two numbers. The result is rounded towards - * zero. - */ - function average(uint256 a, uint256 b) internal pure returns (uint256) { - // (a + b) / 2 can overflow, so we distribute - return (a / 2) + (b / 2) + (((a % 2) + (b % 2)) / 2); - } - - function quadraticPricing(uint256 payment_, uint256 multiplier_) internal pure returns (uint256) { - return sqrrt(mul(multiplier_, payment_)); - } - - function bondingCurve(uint256 supply_, uint256 multiplier_) internal pure returns (uint256) { - return mul(multiplier_, supply_); - } -} - -// OpenZeppelin Contracts (last updated v4.7.0) (token/ERC20/utils/SafeERC20.sol) - - - - - -// OpenZeppelin Contracts v4.4.1 (token/ERC20/extensions/draft-IERC20Permit.sol) - - - -/** - * @dev Interface of the ERC20 Permit extension allowing approvals to be made via signatures, as defined in - * https://eips.ethereum.org/EIPS/eip-2612[EIP-2612]. - * - * Adds the {permit} method, which can be used to change an account's ERC20 allowance (see {IERC20-allowance}) by - * presenting a message signed by the account. By not relying on {IERC20-approve}, the token holder account doesn't - * need to send a transaction, and thus is not required to hold Ether at all. - */ -interface IERC20Permit { - /** - * @dev Sets `value` as the allowance of `spender` over ``owner``'s tokens, - * given ``owner``'s signed approval. - * - * IMPORTANT: The same issues {IERC20-approve} has related to transaction - * ordering also apply here. - * - * Emits an {Approval} event. - * - * Requirements: - * - * - `spender` cannot be the zero address. - * - `deadline` must be a timestamp in the future. - * - `v`, `r` and `s` must be a valid `secp256k1` signature from `owner` - * over the EIP712-formatted function arguments. - * - the signature must use ``owner``'s current nonce (see {nonces}). - * - * For more information on the signature format, see the - * https://eips.ethereum.org/EIPS/eip-2612#specification[relevant EIP - * section]. - */ - function permit( - address owner, - address spender, - uint256 value, - uint256 deadline, - uint8 v, - bytes32 r, - bytes32 s - ) external; - - /** - * @dev Returns the current nonce for `owner`. This value must be - * included whenever a signature is generated for {permit}. - * - * Every successful call to {permit} increases ``owner``'s nonce by one. This - * prevents a signature from being used multiple times. - */ - function nonces(address owner) external view returns (uint256); - - /** - * @dev Returns the domain separator used in the encoding of the signature for {permit}, as defined by {EIP712}. - */ - // solhint-disable-next-line func-name-mixedcase - function DOMAIN_SEPARATOR() external view returns (bytes32); -} - - - -/** - * @title SafeERC20 - * @dev Wrappers around ERC20 operations that throw on failure (when the token - * contract returns false). Tokens that return no value (and instead revert or - * throw on failure) are also supported, non-reverting calls are assumed to be - * successful. - * To use this library you can add a `using SafeERC20 for IERC20;` statement to your contract, - * which allows you to call the safe operations as `token.safeTransfer(...)`, etc. - */ -library SafeERC20 { - using Address for address; - - function safeTransfer( - IERC20 token, - address to, - uint256 value - ) internal { - _callOptionalReturn(token, abi.encodeWithSelector(token.transfer.selector, to, value)); - } - - function safeTransferFrom( - IERC20 token, - address from, - address to, - uint256 value - ) internal { - _callOptionalReturn(token, abi.encodeWithSelector(token.transferFrom.selector, from, to, value)); - } - - /** - * @dev Deprecated. This function has issues similar to the ones found in - * {IERC20-approve}, and its usage is discouraged. - * - * Whenever possible, use {safeIncreaseAllowance} and - * {safeDecreaseAllowance} instead. - */ - function safeApprove( - IERC20 token, - address spender, - uint256 value - ) internal { - // safeApprove should only be called when setting an initial allowance, - // or when resetting it to zero. To increase and decrease it, use - // 'safeIncreaseAllowance' and 'safeDecreaseAllowance' - require( - (value == 0) || (token.allowance(address(this), spender) == 0), - "SafeERC20: approve from non-zero to non-zero allowance" - ); - _callOptionalReturn(token, abi.encodeWithSelector(token.approve.selector, spender, value)); - } - - function safeIncreaseAllowance( - IERC20 token, - address spender, - uint256 value - ) internal { - uint256 newAllowance = token.allowance(address(this), spender) + value; - _callOptionalReturn(token, abi.encodeWithSelector(token.approve.selector, spender, newAllowance)); - } - - function safeDecreaseAllowance( - IERC20 token, - address spender, - uint256 value - ) internal { - unchecked { - uint256 oldAllowance = token.allowance(address(this), spender); - require(oldAllowance >= value, "SafeERC20: decreased allowance below zero"); - uint256 newAllowance = oldAllowance - value; - _callOptionalReturn(token, abi.encodeWithSelector(token.approve.selector, spender, newAllowance)); - } - } - - function safePermit( - IERC20Permit token, - address owner, - address spender, - uint256 value, - uint256 deadline, - uint8 v, - bytes32 r, - bytes32 s - ) internal { - uint256 nonceBefore = token.nonces(owner); - token.permit(owner, spender, value, deadline, v, r, s); - uint256 nonceAfter = token.nonces(owner); - require(nonceAfter == nonceBefore + 1, "SafeERC20: permit did not succeed"); - } - - /** - * @dev Imitates a Solidity high-level call (i.e. a regular function call to a contract), relaxing the requirement - * on the return value: the return value is optional (but if data is returned, it must not be false). - * @param token The token targeted by the call. - * @param data The call data (encoded using abi.encode or one of its variants). - */ - function _callOptionalReturn(IERC20 token, bytes memory data) private { - // We need to perform a low level call here, to bypass Solidity's return data size checking mechanism, since - // we're implementing it ourselves. We use {Address.functionCall} to perform this call, which verifies that - // the target address contains contract code and also asserts for success in the low-level call. - - bytes memory returndata = address(token).functionCall(data, "SafeERC20: low-level call failed"); - if (returndata.length > 0) { - // Return data is optional - require(abi.decode(returndata, (bool)), "SafeERC20: ERC20 operation did not succeed"); - } - } -} - - - - - - - - - - - - - - -/** - * @dev Provides information about the current execution context, including the - * sender of the transaction and its data. While these are generally available - * via msg.sender and msg.data, they should not be accessed in such a direct - * manner, since when dealing with meta-transactions the account sending and - * paying for execution may not be the actual sender (as far as an application - * is concerned). - * - * This contract is only required for intermediate, library-like contracts. - */ -abstract contract Context { - function _msgSender() internal view virtual returns (address) { - return msg.sender; - } - - function _msgData() internal view virtual returns (bytes calldata) { - return msg.data; - } -} - - -/** - * @dev Contract module which provides a basic access control mechanism, where - * there is an account (an owner) that can be granted exclusive access to - * specific functions. - * - * By default, the owner account will be the one that deploys the contract. This - * can later be changed with {transferOwnership}. - * - * This module is used through inheritance. It will make available the modifier - * `onlyOwner`, which can be applied to your functions to restrict their use to - * the owner. - */ -abstract contract Ownable is Context { - address private _owner; - - event OwnershipTransferred(address indexed previousOwner, address indexed newOwner); - - /** - * @dev Initializes the contract setting the deployer as the initial owner. - */ - constructor() { - _transferOwnership(_msgSender()); - } - - /** - * @dev Throws if called by any account other than the owner. - */ - modifier onlyOwner() { - _checkOwner(); - _; - } - - /** - * @dev Returns the address of the current owner. - */ - function owner() public view virtual returns (address) { - return _owner; - } - - /** - * @dev Throws if the sender is not the owner. - */ - function _checkOwner() internal view virtual { - require(owner() == _msgSender(), "Ownable: caller is not the owner"); - } - - /** - * @dev Leaves the contract without owner. It will not be possible to call - * `onlyOwner` functions anymore. Can only be called by the current owner. - * - * NOTE: Renouncing ownership will leave the contract without an owner, - * thereby removing any functionality that is only available to the owner. - */ - function renounceOwnership() public virtual onlyOwner { - _transferOwnership(address(0)); - } - - /** - * @dev Transfers ownership of the contract to a new account (`newOwner`). - * Can only be called by the current owner. - */ - function transferOwnership(address newOwner) public virtual onlyOwner { - require(newOwner != address(0), "Ownable: new owner is the zero address"); - _transferOwnership(newOwner); - } - - /** - * @dev Transfers ownership of the contract to a new account (`newOwner`). - * Internal function without access restriction. - */ - function _transferOwnership(address newOwner) internal virtual { - address oldOwner = _owner; - _owner = newOwner; - emit OwnershipTransferred(oldOwner, newOwner); - } -} - - -contract Operator is Ownable { - address public operator; - uint256 constant baseRate = 10000; - - modifier onlyOperator { - require(msg.sender == owner() || msg.sender == operator, "no permission"); - _; - } - - function setOperator(address operator_) external onlyOwner { - operator = operator_; - } - - - function getCurrTime() external view returns(uint256) { - return block.timestamp; - } - - function getBlockNum() external view returns(uint256) { - return block.number; - } - -} - - - - - -/** - * @dev Library for managing - * https://en.wikipedia.org/wiki/Set_(abstract_data_type)[sets] of primitive - * types. - * - * Sets have the following properties: - * - * - Elements are added, removed, and checked for existence in constant time - * (O(1)). - * - Elements are enumerated in O(n). No guarantees are made on the ordering. - * - * ``` - * contract Example { - * // Add the library methods - * using EnumerableSet for EnumerableSet.AddressSet; - * - * // Declare a set state variable - * EnumerableSet.AddressSet private mySet; - * } - * ``` - * - * As of v3.3.0, sets of type `bytes32` (`Bytes32Set`), `address` (`AddressSet`) - * and `uint256` (`UintSet`) are supported. - * - * [WARNING] - * ==== - * Trying to delete such a structure from storage will likely result in data corruption, rendering the structure unusable. - * See https://github.com/ethereum/solidity/pull/11843[ethereum/solidity#11843] for more info. - * - * In order to clean an EnumerableSet, you can either remove all elements one by one or create a fresh instance using an array of EnumerableSet. - * ==== - */ - -library EnumerableSet { - // To implement this library for multiple types with as little code - // repetition as possible, we write it in terms of a generic Set type with - // bytes32 values. - // The Set implementation uses private functions, and user-facing - // implementations (such as AddressSet) are just wrappers around the - // underlying Set. - // This means that we can only create new EnumerableSets for types that fit - // in bytes32. - - struct Set { - // Storage of set values - bytes32[] _values; - // Position of the value in the `values` array, plus 1 because index 0 - // means a value is not in the set. - mapping(bytes32 => uint256) _indexes; - } - - /** - * @dev Add a value to a set. O(1). - * - * Returns true if the value was added to the set, that is if it was not - * already present. - */ - function _add(Set storage set, bytes32 value) private returns (bool) { - if (!_contains(set, value)) { - set._values.push(value); - // The value is stored at length-1, but we add 1 to all indexes - // and use 0 as a sentinel value - set._indexes[value] = set._values.length; - return true; - } else { - return false; - } - } - - /** - * @dev Removes a value from a set. O(1). - * - * Returns true if the value was removed from the set, that is if it was - * present. - */ - function _remove(Set storage set, bytes32 value) private returns (bool) { - // We read and store the value's index to prevent multiple reads from the same storage slot - uint256 valueIndex = set._indexes[value]; - - if (valueIndex != 0) { - // Equivalent to contains(set, value) - // To delete an element from the _values array in O(1), we swap the element to delete with the last one in - // the array, and then remove the last element (sometimes called as 'swap and pop'). - // This modifies the order of the array, as noted in {at}. - - uint256 toDeleteIndex = valueIndex - 1; - uint256 lastIndex = set._values.length - 1; - - if (lastIndex != toDeleteIndex) { - bytes32 lastValue = set._values[lastIndex]; - - // Move the last value to the index where the value to delete is - set._values[toDeleteIndex] = lastValue; - // Update the index for the moved value - set._indexes[lastValue] = valueIndex; // Replace lastValue's index to valueIndex - } - - // Delete the slot where the moved value was stored - set._values.pop(); - - // Delete the index for the deleted slot - delete set._indexes[value]; - - return true; - } else { - return false; - } - } - - /** - * @dev Returns true if the value is in the set. O(1). - */ - function _contains(Set storage set, bytes32 value) private view returns (bool) { - return set._indexes[value] != 0; - } - - /** - * @dev Returns the number of values on the set. O(1). - */ - function _length(Set storage set) private view returns (uint256) { - return set._values.length; - } - - /** - * @dev Returns the value stored at position `index` in the set. O(1). - * - * Note that there are no guarantees on the ordering of values inside the - * array, and it may change when more values are added or removed. - * - * Requirements: - * - * - `index` must be strictly less than {length}. - */ - function _at(Set storage set, uint256 index) private view returns (bytes32) { - return set._values[index]; - } - - /** - * @dev Return the entire set in an array - * - * WARNING: This operation will copy the entire storage to memory, which can be quite expensive. This is designed - * to mostly be used by view accessors that are queried without any gas fees. Developers should keep in mind that - * this function has an unbounded cost, and using it as part of a state-changing function may render the function - * uncallable if the set grows to a point where copying to memory consumes too much gas to fit in a block. - */ - function _values(Set storage set) private view returns (bytes32[] memory) { - return set._values; - } - - // Bytes32Set - - struct Bytes32Set { - Set _inner; - } - - /** - * @dev Add a value to a set. O(1). - * - * Returns true if the value was added to the set, that is if it was not - * already present. - */ - function add(Bytes32Set storage set, bytes32 value) internal returns (bool) { - return _add(set._inner, value); - } - - /** - * @dev Removes a value from a set. O(1). - * - * Returns true if the value was removed from the set, that is if it was - * present. - */ - function remove(Bytes32Set storage set, bytes32 value) internal returns (bool) { - return _remove(set._inner, value); - } - - /** - * @dev Returns true if the value is in the set. O(1). - */ - function contains(Bytes32Set storage set, bytes32 value) internal view returns (bool) { - return _contains(set._inner, value); - } - - /** - * @dev Returns the number of values in the set. O(1). - */ - function length(Bytes32Set storage set) internal view returns (uint256) { - return _length(set._inner); - } - - /** - * @dev Returns the value stored at position `index` in the set. O(1). - * - * Note that there are no guarantees on the ordering of values inside the - * array, and it may change when more values are added or removed. - * - * Requirements: - * - * - `index` must be strictly less than {length}. - */ - function at(Bytes32Set storage set, uint256 index) internal view returns (bytes32) { - return _at(set._inner, index); - } - - /** - * @dev Return the entire set in an array - * - * WARNING: This operation will copy the entire storage to memory, which can be quite expensive. This is designed - * to mostly be used by view accessors that are queried without any gas fees. Developers should keep in mind that - * this function has an unbounded cost, and using it as part of a state-changing function may render the function - * uncallable if the set grows to a point where copying to memory consumes too much gas to fit in a block. - */ - function values(Bytes32Set storage set) internal view returns (bytes32[] memory) { - return _values(set._inner); - } - - // AddressSet - - struct AddressSet { - Set _inner; - } - - /** - * @dev Add a value to a set. O(1). - * - * Returns true if the value was added to the set, that is if it was not - * already present. - */ - function add(AddressSet storage set, address value) internal returns (bool) { - return _add(set._inner, bytes32(uint256(uint160(value)))); - } - - /** - * @dev Removes a value from a set. O(1). - * - * Returns true if the value was removed from the set, that is if it was - * present. - */ - function remove(AddressSet storage set, address value) internal returns (bool) { - return _remove(set._inner, bytes32(uint256(uint160(value)))); - } - - /** - * @dev Returns true if the value is in the set. O(1). - */ - function contains(AddressSet storage set, address value) internal view returns (bool) { - return _contains(set._inner, bytes32(uint256(uint160(value)))); - } - - /** - * @dev Returns the number of values in the set. O(1). - */ - function length(AddressSet storage set) internal view returns (uint256) { - return _length(set._inner); - } - - /** - * @dev Returns the value stored at position `index` in the set. O(1). - * - * Note that there are no guarantees on the ordering of values inside the - * array, and it may change when more values are added or removed. - * - * Requirements: - * - * - `index` must be strictly less than {length}. - */ - function at(AddressSet storage set, uint256 index) internal view returns (address) { - return address(uint160(uint256(_at(set._inner, index)))); - } - - /** - * @dev Return the entire set in an array - * - * WARNING: This operation will copy the entire storage to memory, which can be quite expensive. This is designed - * to mostly be used by view accessors that are queried without any gas fees. Developers should keep in mind that - * this function has an unbounded cost, and using it as part of a state-changing function may render the function - * uncallable if the set grows to a point where copying to memory consumes too much gas to fit in a block. - */ - function values(AddressSet storage set) internal view returns (address[] memory) { - bytes32[] memory store = _values(set._inner); - address[] memory result; - - /// @solidity memory-safe-assembly - assembly { - result := store - } - - return result; - } - - // UintSet - - struct UintSet { - Set _inner; - } - - /** - * @dev Add a value to a set. O(1). - * - * Returns true if the value was added to the set, that is if it was not - * already present. - */ - function add(UintSet storage set, uint256 value) internal returns (bool) { - return _add(set._inner, bytes32(value)); - } - - /** - * @dev Removes a value from a set. O(1). - * - * Returns true if the value was removed from the set, that is if it was - * present. - */ - function remove(UintSet storage set, uint256 value) internal returns (bool) { - return _remove(set._inner, bytes32(value)); - } - - /** - * @dev Returns true if the value is in the set. O(1). - */ - function contains(UintSet storage set, uint256 value) internal view returns (bool) { - return _contains(set._inner, bytes32(value)); - } - - /** - * @dev Returns the number of values on the set. O(1). - */ - function length(UintSet storage set) internal view returns (uint256) { - return _length(set._inner); - } - - /** - * @dev Returns the value stored at position `index` in the set. O(1). - * - * Note that there are no guarantees on the ordering of values inside the - * array, and it may change when more values are added or removed. - * - * Requirements: - * - * - `index` must be strictly less than {length}. - */ - function at(UintSet storage set, uint256 index) internal view returns (uint256) { - return uint256(_at(set._inner, index)); - } - - /** - * @dev Return the entire set in an array - * - * WARNING: This operation will copy the entire storage to memory, which can be quite expensive. This is designed - * to mostly be used by view accessors that are queried without any gas fees. Developers should keep in mind that - * this function has an unbounded cost, and using it as part of a state-changing function may render the function - * uncallable if the set grows to a point where copying to memory consumes too much gas to fit in a block. - */ - function values(UintSet storage set) internal view returns (uint256[] memory) { - bytes32[] memory store = _values(set._inner); - uint256[] memory result; - - /// @solidity memory-safe-assembly - assembly { - result := store - } - - return result; - } -} - - -contract ActivityPool is Operator { - using SafeMath for uint256; - using SafeERC20 for IERC20; - using EnumerableSet for EnumerableSet.AddressSet; - using EnumerableSet for EnumerableSet.UintSet; - - event AddNewAct(uint256 id); - event Bet(address user, uint256 pID, uint256 bType, uint256 amount, uint256 time); - event SetPrize(uint256 pID, uint256 bType); - event Claim(address user, uint256 pID, uint256 bType, uint256 amount); - event RemovePeriodAct(uint256 pID); - - uint256 public constant muti = 1e18; - uint256 public periodID; - uint256 public betID; - - struct UserInfo { - address user; - uint256 pID; - uint256 amount; - uint256 betTime; - uint256 bType; - uint256 claimAmount; - } - - struct ActInfo { - string name; - string aName; - string bName; - address rewardToken; - uint256 startTime; - uint256 endTime; - uint256 minAmount; - uint256 maxAmount; - uint256 aAmount; - uint256 bAmount; - uint256 winType; - bool isBet; - } - - struct TimeInfo { - uint256 time; - uint256 aAmount; - uint256 bAmount; - } - - struct BestInfo { - address aUser; - address bUser; - uint256 aBet; - uint256 bBet; - } - - mapping(uint256 => BestInfo) bestInfo; - mapping(uint256 => uint256) public timeID; - mapping(uint256 => mapping(uint256 => TimeInfo)) public timeInfo; - mapping(address => mapping(uint256 => uint256)) public userBet; - mapping(uint256 => UserInfo) public betInfo; - mapping(uint256 => uint256) public perAmount; - mapping(uint256 => ActInfo) public actInfo; - mapping(uint256 => mapping(uint256 => string)) public descripName; - - mapping(address => EnumerableSet.UintSet) userPid; - mapping(uint256 => EnumerableSet.AddressSet) aUsers; - mapping(uint256 => EnumerableSet.AddressSet) bUsers; - EnumerableSet.UintSet activePeriod; - EnumerableSet.UintSet removePeriod; - - function addNewAct( - string memory name, - string memory aName, - string memory bName, - address token, - uint256 startTime, - uint256 endTime, - uint256 minAmount, - uint256 maxAmount - ) external onlyOperator { - - checkAdd(msg.sender, startTime, endTime, minAmount, maxAmount); - uint256 id = ++periodID; - actInfo[id].name = name; - actInfo[id].aName = aName; - actInfo[id].bName = bName; - actInfo[id].startTime = startTime; - actInfo[id].endTime = endTime; - actInfo[id].minAmount = minAmount; - actInfo[id].maxAmount = maxAmount; - actInfo[id].rewardToken = token; - descripName[id][1] = aName; - descripName[id][2] = bName; - activePeriod.add(id); - - emit AddNewAct(id); - } - - - function removePeriodAct(uint256 pID) external onlyOperator { - checkRemove(pID); - - activePeriod.remove(pID); - removePeriod.add(pID); - - emit RemovePeriodAct(pID); - } - - - function bet(uint256 pID, uint256 bType, uint256 amount) external payable { - checkBet(msg.sender, pID, bType, amount); - if(actInfo[pID].rewardToken == address(0)) { - require(msg.value == amount, "value err"); - } else { - require(msg.value == 0, "value amount err"); - } - - if(bType == 1) { - if(amount > bestInfo[pID].aBet) { - bestInfo[pID].aUser = msg.sender; - bestInfo[pID].aBet = amount; - } - } else { - if(amount > bestInfo[pID].bBet) { - bestInfo[pID].bUser = msg.sender; - bestInfo[pID].bBet = amount; - } - } - - userPid[msg.sender].add(pID); - uint256 id = ++betID; - userBet[msg.sender][pID] = id; - - if(bType == 1) { - aUsers[pID].add(msg.sender); - actInfo[pID].aAmount = actInfo[pID].aAmount.add(amount); - } else { - bUsers[pID].add(msg.sender); - actInfo[pID].bAmount = actInfo[pID].bAmount.add(amount); - } - - actInfo[pID].isBet = true; - betInfo[id].user = msg.sender; - betInfo[id].pID = pID; - betInfo[id].amount = amount; - betInfo[id].betTime = block.timestamp; - betInfo[id].bType = bType; - - uint256 tID = ++timeID[pID]; - timeInfo[pID][tID].time = block.timestamp; - timeInfo[pID][tID].aAmount = actInfo[pID].aAmount; - timeInfo[pID][tID].bAmount = actInfo[pID].bAmount; - - if(actInfo[pID].rewardToken != address(0)) { - IERC20(actInfo[pID].rewardToken).safeTransferFrom(msg.sender, address(this), amount); - } - emit Bet(msg.sender, pID, bType, amount, betInfo[id].betTime); - } - - function setPrize(uint256 pID, uint256 bType) external onlyOperator { - checkSetPrize(msg.sender, pID, bType); - - if(block.timestamp <= actInfo[pID].startTime) { - actInfo[pID].startTime = block.timestamp; - - } - actInfo[pID].endTime = block.timestamp; - - actInfo[pID].winType = bType; - perAmount[pID] = getPerAmount(pID, bType); - - emit SetPrize(pID, bType); - } - - function recive() public payable {} - - function claim(uint256 pID) external { - uint256 amount = checkClaim(msg.sender, pID); - - uint256 id = userBet[msg.sender][pID]; - betInfo[id].claimAmount = amount; - if(actInfo[pID].rewardToken != address(0)) { - IERC20(actInfo[pID].rewardToken).safeTransfer(msg.sender, amount); - } else { - payable(msg.sender).transfer(amount); - } - - emit Claim(msg.sender, pID, betInfo[id].bType, amount); - } - - function checkClaim(address user, uint256 pID) public view returns(uint256 amount) { - require(userPid[user].contains(pID), "not bet"); - uint256 id = userBet[user][pID]; - require(betInfo[id].user == user, "not user"); - require(actInfo[pID].winType != 0, "not prize"); - require(betInfo[id].claimAmount == 0, "has claim"); - - if(actInfo[pID].winType != 3) { - require(actInfo[pID].winType == betInfo[id].bType, "not right"); - amount = perAmount[pID].mul(betInfo[id].amount).div(muti); - require(amount > 0, "no amount"); - } else { - amount = betInfo[id].amount; - } - - return amount; - } - - function getActualRate( - address user, - uint256 pID, - uint256 bType, - uint256 amount - ) external view returns(uint256, uint256, bool) { - if(bType < 1 || bType > 2 || !activePeriod.contains(pID)) { - return (0, 0, false); - } else if(userBet[user][pID] != 0 || actInfo[pID].winType != 0 || amount == 0) { - (uint256 ra, uint256 rb) = getRate(pID, timeID[pID]); - return (ra, rb, false); - } else { - (uint256 aAmount, uint256 bAmount) = (actInfo[pID].aAmount, actInfo[pID].bAmount); - if(bType == 1) { - aAmount = aAmount.add(amount); - } else { - bAmount = bAmount.add(amount); - } - - uint256 total = aAmount.add(bAmount); - if(bAmount == 0 && aAmount != 0) { - return (muti, 0, true); - } - if(bAmount != 0 && aAmount == 0) { - return (0, muti, true); - } - return (total.mul(muti).div(aAmount), total.mul(muti).div(bAmount), true); - } - } - - function getRate(uint256 pID, uint256 tID) public view returns(uint256, uint256) { - (uint256 aAmount, uint256 bAmount) = (timeInfo[pID][tID].aAmount, timeInfo[pID][tID].bAmount); - uint256 total = aAmount.add(bAmount); - if(total == 0) { - return (0, 0); - } - if(bAmount == 0 && aAmount != 0) { - return (muti, 0); - } - if(bAmount != 0 && aAmount == 0) { - return (0, muti); - } - return (total.mul(muti).div(aAmount), total.mul(muti).div(bAmount)); - } - - function getBestInfo(uint256 pID) - external - view - returns(address aUser, address bUser, uint256 aBet, uint256 bBet, uint256 aReward, uint256 bReward) - { - aUser = bestInfo[pID].aUser; - bUser = bestInfo[pID].bUser; - aBet = bestInfo[pID].aBet; - bBet = bestInfo[pID].bBet; - aReward = getPerAmount(pID, 1).mul(aBet).div(muti); - bReward = getPerAmount(pID, 2).mul(bBet).div(muti); - } - - function getPerAmount(uint256 pID, uint256 bType) public view returns(uint256) { - uint256 total = actInfo[pID].aAmount.add(actInfo[pID].bAmount); - if(total == 0) { - return 0; - } - - if(actInfo[pID].winType == 3) { - return muti; - } - - if(bType == 1) { - if(actInfo[pID].aAmount == 0 || actInfo[pID].winType == 2) { - return 0; - } - return total.mul(muti).div(actInfo[pID].aAmount); - } - - if(bType == 2) { - if(actInfo[pID].bAmount == 0 || actInfo[pID].winType == 1) { - return 0; - } - return total.mul(muti).div(actInfo[pID].bAmount); - } - - return 0; - - } - - function checkSetPrize(address user, uint256 pID, uint256 bType) public view returns(bool) { - require(user == owner() || user == operator, "no permission"); - require(bType > 0 && bType <= 3, "type err"); - require(activePeriod.contains(pID), "not active"); - require(actInfo[pID].winType == 0, "has set"); - - return true; - } - - function checkBet( - address user, - uint256 pID, - uint256 bType, - uint256 amount - ) public view returns(bool) { - require(activePeriod.contains(pID), "not active"); - require(actInfo[pID].startTime <= block.timestamp, "not start"); - require(actInfo[pID].endTime > block.timestamp, "has end"); - require(!userPid[user].contains(pID), "has bet"); - require(bType > 0 && bType < 3, "type err"); - require(amount >= actInfo[pID].minAmount && amount <= actInfo[pID].maxAmount, "amount err"); - if(actInfo[pID].rewardToken != address(0)) { - require(IERC20(actInfo[pID].rewardToken).allowance(user, address(this)) >= amount, "not approve enough"); - require(IERC20(actInfo[pID].rewardToken).balanceOf(user) >= amount, "not enough"); - } else { - require(user.balance >= amount, "main token err"); - } - - return true; - } - - - function checkRemove(uint256 pID) public view returns(bool) { - require(activePeriod.contains(pID), "not in"); - require(!actInfo[pID].isBet, "has bet"); - - return true; - } - - function checkAdd( - address user, - uint256 startTime, - uint256 endTime, - uint256 minAmount, - uint256 maxAmount - ) public view returns(bool) { - require(user == owner() || user == operator, "no permission"); - require(startTime > block.timestamp, "startTime err"); - require(endTime > startTime, "endTime err"); - require(minAmount > 0 && maxAmount > minAmount, "amount err"); - - return true; - } - - function getStatus(uint256 pID) external view returns(uint256) { - if(!removePeriod.contains(pID) && !activePeriod.contains(pID)) { - return 5; - } else if(removePeriod.contains(pID)) { - return 6; - } else if(block.timestamp < actInfo[pID].startTime) { - return 1; - } else if ( - actInfo[pID].startTime <= block.timestamp && - actInfo[pID].endTime > block.timestamp - ) { - return 2; - } else if (actInfo[pID].endTime <= block.timestamp && actInfo[pID].winType == 0){ - return 3; - } else if(actInfo[pID].winType != 0) { - return 4; - } - return 0; - } - - function getUserPidNum(address user) external view returns(uint256) { - return userPid[user].length(); - } - - function getUserPid(address user, uint256 index) external view returns(uint256) { - return userPid[user].at(index); - } - - function getAUsersNum(uint256 pID) external view returns(uint256) { - return aUsers[pID].length(); - } - - function getAUsers(uint256 pID, uint256 index) external view returns(address) { - return aUsers[pID].at(index); - } - - function getBUsersNum(uint256 pID) external view returns(uint256) { - return bUsers[pID].length(); - } - - function getBUsers(uint256 pID, uint256 index) external view returns(address) { - return bUsers[pID].at(index); - } - - function getActivePeriodNum() external view returns(uint256) { - return activePeriod.length(); - } - - function getActivePeriod(uint256 index) external view returns(uint256) { - return activePeriod.at(index); - } - - function getRemovePeriodNum() external view returns(uint256) { - return removePeriod.length(); - } - - function getRemovePeriod(uint256 index) external view returns(uint256) { - return removePeriod.at(index); - } -} \ No newline at end of file diff --git a/app/api/uploads/ActivityPool-1729822490209-444268394.sol b/app/api/uploads/ActivityPool-1729822490209-444268394.sol deleted file mode 100644 index daf3372..0000000 --- a/app/api/uploads/ActivityPool-1729822490209-444268394.sol +++ /dev/null @@ -1,1648 +0,0 @@ -// SPDX-License-Identifier: MIT -// OpenZeppelin Contracts (last updated v4.7.0) (utils/Address.sol) - -pragma solidity ^0.8.1; - -/** - * @dev Collection of functions related to the address type - */ -library Address { - /** - * @dev Returns true if `account` is a contract. - * - * [IMPORTANT] - * ==== - * It is unsafe to assume that an address for which this function returns - * false is an externally-owned account (EOA) and not a contract. - * - * Among others, `isContract` will return false for the following - * types of addresses: - * - * - an externally-owned account - * - a contract in construction - * - an address where a contract will be created - * - an address where a contract lived, but was destroyed - * ==== - * - * [IMPORTANT] - * ==== - * You shouldn't rely on `isContract` to protect against flash loan attacks! - * - * Preventing calls from contracts is highly discouraged. It breaks composability, breaks support for smart wallets - * like Gnosis Safe, and does not provide security since it can be circumvented by calling from a contract - * constructor. - * ==== - */ - function isContract(address account) internal view returns (bool) { - // This method relies on extcodesize/address.code.length, which returns 0 - // for contracts in construction, since the code is only stored at the end - // of the constructor execution. - - return account.code.length > 0; - } - - /** - * @dev Replacement for Solidity's `transfer`: sends `amount` wei to - * `recipient`, forwarding all available gas and reverting on errors. - * - * https://eips.ethereum.org/EIPS/eip-1884[EIP1884] increases the gas cost - * of certain opcodes, possibly making contracts go over the 2300 gas limit - * imposed by `transfer`, making them unable to receive funds via - * `transfer`. {sendValue} removes this limitation. - * - * https://diligence.consensys.net/posts/2019/09/stop-using-soliditys-transfer-now/[Learn more]. - * - * IMPORTANT: because control is transferred to `recipient`, care must be - * taken to not create reentrancy vulnerabilities. Consider using - * {ReentrancyGuard} or the - * https://solidity.readthedocs.io/en/v0.5.11/security-considerations.html#use-the-checks-effects-interactions-pattern[checks-effects-interactions pattern]. - */ - function sendValue(address payable recipient, uint256 amount) internal { - require(address(this).balance >= amount, "Address: insufficient balance"); - - (bool success, ) = recipient.call{value: amount}(""); - require(success, "Address: unable to send value, recipient may have reverted"); - } - - /** - * @dev Performs a Solidity function call using a low level `call`. A - * plain `call` is an unsafe replacement for a function call: use this - * function instead. - * - * If `target` reverts with a revert reason, it is bubbled up by this - * function (like regular Solidity function calls). - * - * Returns the raw returned data. To convert to the expected return value, - * use https://solidity.readthedocs.io/en/latest/units-and-global-variables.html?highlight=abi.decode#abi-encoding-and-decoding-functions[`abi.decode`]. - * - * Requirements: - * - * - `target` must be a contract. - * - calling `target` with `data` must not revert. - * - * _Available since v3.1._ - */ - function functionCall(address target, bytes memory data) internal returns (bytes memory) { - return functionCallWithValue(target, data, 0, "Address: low-level call failed"); - } - - /** - * @dev Same as {xref-Address-functionCall-address-bytes-}[`functionCall`], but with - * `errorMessage` as a fallback revert reason when `target` reverts. - * - * _Available since v3.1._ - */ - function functionCall( - address target, - bytes memory data, - string memory errorMessage - ) internal returns (bytes memory) { - return functionCallWithValue(target, data, 0, errorMessage); - } - - /** - * @dev Same as {xref-Address-functionCall-address-bytes-}[`functionCall`], - * but also transferring `value` wei to `target`. - * - * Requirements: - * - * - the calling contract must have an ETH balance of at least `value`. - * - the called Solidity function must be `payable`. - * - * _Available since v3.1._ - */ - function functionCallWithValue( - address target, - bytes memory data, - uint256 value - ) internal returns (bytes memory) { - return functionCallWithValue(target, data, value, "Address: low-level call with value failed"); - } - - /** - * @dev Same as {xref-Address-functionCallWithValue-address-bytes-uint256-}[`functionCallWithValue`], but - * with `errorMessage` as a fallback revert reason when `target` reverts. - * - * _Available since v3.1._ - */ - function functionCallWithValue( - address target, - bytes memory data, - uint256 value, - string memory errorMessage - ) internal returns (bytes memory) { - require(address(this).balance >= value, "Address: insufficient balance for call"); - (bool success, bytes memory returndata) = target.call{value: value}(data); - return verifyCallResultFromTarget(target, success, returndata, errorMessage); - } - - /** - * @dev Same as {xref-Address-functionCall-address-bytes-}[`functionCall`], - * but performing a static call. - * - * _Available since v3.3._ - */ - function functionStaticCall(address target, bytes memory data) internal view returns (bytes memory) { - return functionStaticCall(target, data, "Address: low-level static call failed"); - } - - /** - * @dev Same as {xref-Address-functionCall-address-bytes-string-}[`functionCall`], - * but performing a static call. - * - * _Available since v3.3._ - */ - function functionStaticCall( - address target, - bytes memory data, - string memory errorMessage - ) internal view returns (bytes memory) { - (bool success, bytes memory returndata) = target.staticcall(data); - return verifyCallResultFromTarget(target, success, returndata, errorMessage); - } - - /** - * @dev Same as {xref-Address-functionCall-address-bytes-}[`functionCall`], - * but performing a delegate call. - * - * _Available since v3.4._ - */ - function functionDelegateCall(address target, bytes memory data) internal returns (bytes memory) { - return functionDelegateCall(target, data, "Address: low-level delegate call failed"); - } - - /** - * @dev Same as {xref-Address-functionCall-address-bytes-string-}[`functionCall`], - * but performing a delegate call. - * - * _Available since v3.4._ - */ - function functionDelegateCall( - address target, - bytes memory data, - string memory errorMessage - ) internal returns (bytes memory) { - (bool success, bytes memory returndata) = target.delegatecall(data); - return verifyCallResultFromTarget(target, success, returndata, errorMessage); - } - - /** - * @dev Tool to verify that a low level call to smart-contract was successful, and revert (either by bubbling - * the revert reason or using the provided one) in case of unsuccessful call or if target was not a contract. - * - * _Available since v4.8._ - */ - function verifyCallResultFromTarget( - address target, - bool success, - bytes memory returndata, - string memory errorMessage - ) internal view returns (bytes memory) { - if (success) { - if (returndata.length == 0) { - // only check isContract if the call was successful and the return data is empty - // otherwise we already know that it was a contract - require(isContract(target), "Address: call to non-contract"); - } - return returndata; - } else { - _revert(returndata, errorMessage); - } - } - - /** - * @dev Tool to verify that a low level call was successful, and revert if it wasn't, either by bubbling the - * revert reason or using the provided one. - * - * _Available since v4.3._ - */ - function verifyCallResult( - bool success, - bytes memory returndata, - string memory errorMessage - ) internal pure returns (bytes memory) { - if (success) { - return returndata; - } else { - _revert(returndata, errorMessage); - } - } - - function _revert(bytes memory returndata, string memory errorMessage) private pure { - // Look for revert reason and bubble it up if present - if (returndata.length > 0) { - // The easiest way to bubble the revert reason is using memory via assembly - /// @solidity memory-safe-assembly - assembly { - let returndata_size := mload(returndata) - revert(add(32, returndata), returndata_size) - } - } else { - revert(errorMessage); - } - } -} - -// OpenZeppelin Contracts (last updated v4.6.0) (token/ERC20/IERC20.sol) - - - -/** - * @dev Interface of the ERC20 standard as defined in the EIP. - */ -interface IERC20 { - /** - * @dev Emitted when `value` tokens are moved from one account (`from`) to - * another (`to`). - * - * Note that `value` may be zero. - */ - event Transfer(address indexed from, address indexed to, uint256 value); - - /** - * @dev Emitted when the allowance of a `spender` for an `owner` is set by - * a call to {approve}. `value` is the new allowance. - */ - event Approval(address indexed owner, address indexed spender, uint256 value); - - /** - * @dev Returns the amount of tokens in existence. - */ - function totalSupply() external view returns (uint256); - - /** - * @dev Returns the amount of tokens owned by `account`. - */ - function balanceOf(address account) external view returns (uint256); - - /** - * @dev Moves `amount` tokens from the caller's account to `to`. - * - * Returns a boolean value indicating whether the operation succeeded. - * - * Emits a {Transfer} event. - */ - function transfer(address to, uint256 amount) external returns (bool); - - /** - * @dev Returns the remaining number of tokens that `spender` will be - * allowed to spend on behalf of `owner` through {transferFrom}. This is - * zero by default. - * - * This value changes when {approve} or {transferFrom} are called. - */ - function allowance(address owner, address spender) external view returns (uint256); - - /** - * @dev Sets `amount` as the allowance of `spender` over the caller's tokens. - * - * Returns a boolean value indicating whether the operation succeeded. - * - * IMPORTANT: Beware that changing an allowance with this method brings the risk - * that someone may use both the old and the new allowance by unfortunate - * transaction ordering. One possible solution to mitigate this race - * condition is to first reduce the spender's allowance to 0 and set the - * desired value afterwards: - * https://github.com/ethereum/EIPs/issues/20#issuecomment-263524729 - * - * Emits an {Approval} event. - */ - function approve(address spender, uint256 amount) external returns (bool); - - /** - * @dev Moves `amount` tokens from `from` to `to` using the - * allowance mechanism. `amount` is then deducted from the caller's - * allowance. - * - * Returns a boolean value indicating whether the operation succeeded. - * - * Emits a {Transfer} event. - */ - function transferFrom( - address from, - address to, - uint256 amount - ) external returns (bool); - - - function mint(address account_, uint256 amount_) external; - - function burn(uint256 amount) external; - -} - - - - - - - - - - - -/** - * @dev Wrappers over Solidity's arithmetic operations with added overflow - * checks. - * - * Arithmetic operations in Solidity wrap on overflow. This can easily result - * in bugs, because programmers usually assume that an overflow raises an - * error, which is the standard behavior in high level programming languages. - * `SafeMath` restores this intuition by reverting the transaction when an - * operation overflows. - * - * Using this library instead of the unchecked operations eliminates an entire - * class of bugs, so it's recommended to use it always. - */ -library SafeMath { - /** - * @dev Returns the addition of two unsigned integers, reverting on - * overflow. - * - * Counterpart to Solidity's `+` operator. - * - * Requirements: - * - * - Addition cannot overflow. - */ - function add(uint256 a, uint256 b) internal pure returns (uint256) { - uint256 c = a + b; - require(c >= a, "SafeMath: addition overflow"); - - return c; - } - - /** - * @dev Returns the subtraction of two unsigned integers, reverting on - * overflow (when the result is negative). - * - * Counterpart to Solidity's `-` operator. - * - * Requirements: - * - * - Subtraction cannot overflow. - */ - function sub(uint256 a, uint256 b) internal pure returns (uint256) { - return sub(a, b, "SafeMath: subtraction overflow"); - } - - /** - * @dev Returns the subtraction of two unsigned integers, reverting with custom message on - * overflow (when the result is negative). - * - * Counterpart to Solidity's `-` operator. - * - * Requirements: - * - * - Subtraction cannot overflow. - */ - function sub( - uint256 a, - uint256 b, - string memory errorMessage - ) internal pure returns (uint256) { - require(b <= a, errorMessage); - uint256 c = a - b; - - return c; - } - - /** - * @dev Returns the multiplication of two unsigned integers, reverting on - * overflow. - * - * Counterpart to Solidity's `*` operator. - * - * Requirements: - * - * - Multiplication cannot overflow. - */ - function mul(uint256 a, uint256 b) internal pure returns (uint256) { - // Gas optimization: this is cheaper than requiring 'a' not being zero, but the - // benefit is lost if 'b' is also tested. - // See: https://github.com/OpenZeppelin/openzeppelin-contracts/pull/522 - if (a == 0) { - return 0; - } - - uint256 c = a * b; - require(c / a == b, "SafeMath: multiplication overflow"); - - return c; - } - - /** - * @dev Returns the integer division of two unsigned integers. Reverts on - * division by zero. The result is rounded towards zero. - * - * Counterpart to Solidity's `/` operator. Note: this function uses a - * `revert` opcode (which leaves remaining gas untouched) while Solidity - * uses an invalid opcode to revert (consuming all remaining gas). - * - * Requirements: - * - * - The divisor cannot be zero. - */ - function div(uint256 a, uint256 b) internal pure returns (uint256) { - return div(a, b, "SafeMath: division by zero"); - } - - /** - * @dev Returns the integer division of two unsigned integers. Reverts with custom message on - * division by zero. The result is rounded towards zero. - * - * Counterpart to Solidity's `/` operator. Note: this function uses a - * `revert` opcode (which leaves remaining gas untouched) while Solidity - * uses an invalid opcode to revert (consuming all remaining gas). - * - * Requirements: - * - * - The divisor cannot be zero. - */ - function div( - uint256 a, - uint256 b, - string memory errorMessage - ) internal pure returns (uint256) { - require(b > 0, errorMessage); - uint256 c = a / b; - // assert(a == b * c + a % b); // There is no case in which this doesn't hold - - return c; - } - - /** - * @dev Returns the remainder of dividing two unsigned integers. (unsigned integer modulo), - * Reverts when dividing by zero. - * - * Counterpart to Solidity's `%` operator. This function uses a `revert` - * opcode (which leaves remaining gas untouched) while Solidity uses an - * invalid opcode to revert (consuming all remaining gas). - * - * Requirements: - * - * - The divisor cannot be zero. - */ - function mod(uint256 a, uint256 b) internal pure returns (uint256) { - return mod(a, b, "SafeMath: modulo by zero"); - } - - /** - * @dev Returns the remainder of dividing two unsigned integers. (unsigned integer modulo), - * Reverts with custom message when dividing by zero. - * - * Counterpart to Solidity's `%` operator. This function uses a `revert` - * opcode (which leaves remaining gas untouched) while Solidity uses an - * invalid opcode to revert (consuming all remaining gas). - * - * Requirements: - * - * - The divisor cannot be zero. - */ - function mod( - uint256 a, - uint256 b, - string memory errorMessage - ) internal pure returns (uint256) { - require(b != 0, errorMessage); - return a % b; - } - - // babylonian method (https://en.wikipedia.org/wiki/Methods_of_computing_square_roots#Babylonian_method) - function sqrrt(uint256 a) internal pure returns (uint256 c) { - if (a > 3) { - c = a; - uint256 b = add(div(a, 2), 1); - while (b < c) { - c = b; - b = div(add(div(a, b), b), 2); - } - } else if (a != 0) { - c = 1; - } - } - - /* - * Expects percentage to be trailed by 00, - */ - function percentageAmount(uint256 total_, uint8 percentage_) internal pure returns (uint256 percentAmount_) { - return div(mul(total_, percentage_), 1000); - } - - /* - * Expects percentage to be trailed by 00, - */ - function substractPercentage(uint256 total_, uint8 percentageToSub_) internal pure returns (uint256 result_) { - return sub(total_, div(mul(total_, percentageToSub_), 1000)); - } - - function percentageOfTotal(uint256 part_, uint256 total_) internal pure returns (uint256 percent_) { - return div(mul(part_, 100), total_); - } - - /** - * Taken from Hypersonic https://github.com/M2629/HyperSonic/blob/main/Math.sol - * @dev Returns the average of two numbers. The result is rounded towards - * zero. - */ - function average(uint256 a, uint256 b) internal pure returns (uint256) { - // (a + b) / 2 can overflow, so we distribute - return (a / 2) + (b / 2) + (((a % 2) + (b % 2)) / 2); - } - - function quadraticPricing(uint256 payment_, uint256 multiplier_) internal pure returns (uint256) { - return sqrrt(mul(multiplier_, payment_)); - } - - function bondingCurve(uint256 supply_, uint256 multiplier_) internal pure returns (uint256) { - return mul(multiplier_, supply_); - } -} - -// OpenZeppelin Contracts (last updated v4.7.0) (token/ERC20/utils/SafeERC20.sol) - - - - - -// OpenZeppelin Contracts v4.4.1 (token/ERC20/extensions/draft-IERC20Permit.sol) - - - -/** - * @dev Interface of the ERC20 Permit extension allowing approvals to be made via signatures, as defined in - * https://eips.ethereum.org/EIPS/eip-2612[EIP-2612]. - * - * Adds the {permit} method, which can be used to change an account's ERC20 allowance (see {IERC20-allowance}) by - * presenting a message signed by the account. By not relying on {IERC20-approve}, the token holder account doesn't - * need to send a transaction, and thus is not required to hold Ether at all. - */ -interface IERC20Permit { - /** - * @dev Sets `value` as the allowance of `spender` over ``owner``'s tokens, - * given ``owner``'s signed approval. - * - * IMPORTANT: The same issues {IERC20-approve} has related to transaction - * ordering also apply here. - * - * Emits an {Approval} event. - * - * Requirements: - * - * - `spender` cannot be the zero address. - * - `deadline` must be a timestamp in the future. - * - `v`, `r` and `s` must be a valid `secp256k1` signature from `owner` - * over the EIP712-formatted function arguments. - * - the signature must use ``owner``'s current nonce (see {nonces}). - * - * For more information on the signature format, see the - * https://eips.ethereum.org/EIPS/eip-2612#specification[relevant EIP - * section]. - */ - function permit( - address owner, - address spender, - uint256 value, - uint256 deadline, - uint8 v, - bytes32 r, - bytes32 s - ) external; - - /** - * @dev Returns the current nonce for `owner`. This value must be - * included whenever a signature is generated for {permit}. - * - * Every successful call to {permit} increases ``owner``'s nonce by one. This - * prevents a signature from being used multiple times. - */ - function nonces(address owner) external view returns (uint256); - - /** - * @dev Returns the domain separator used in the encoding of the signature for {permit}, as defined by {EIP712}. - */ - // solhint-disable-next-line func-name-mixedcase - function DOMAIN_SEPARATOR() external view returns (bytes32); -} - - - -/** - * @title SafeERC20 - * @dev Wrappers around ERC20 operations that throw on failure (when the token - * contract returns false). Tokens that return no value (and instead revert or - * throw on failure) are also supported, non-reverting calls are assumed to be - * successful. - * To use this library you can add a `using SafeERC20 for IERC20;` statement to your contract, - * which allows you to call the safe operations as `token.safeTransfer(...)`, etc. - */ -library SafeERC20 { - using Address for address; - - function safeTransfer( - IERC20 token, - address to, - uint256 value - ) internal { - _callOptionalReturn(token, abi.encodeWithSelector(token.transfer.selector, to, value)); - } - - function safeTransferFrom( - IERC20 token, - address from, - address to, - uint256 value - ) internal { - _callOptionalReturn(token, abi.encodeWithSelector(token.transferFrom.selector, from, to, value)); - } - - /** - * @dev Deprecated. This function has issues similar to the ones found in - * {IERC20-approve}, and its usage is discouraged. - * - * Whenever possible, use {safeIncreaseAllowance} and - * {safeDecreaseAllowance} instead. - */ - function safeApprove( - IERC20 token, - address spender, - uint256 value - ) internal { - // safeApprove should only be called when setting an initial allowance, - // or when resetting it to zero. To increase and decrease it, use - // 'safeIncreaseAllowance' and 'safeDecreaseAllowance' - require( - (value == 0) || (token.allowance(address(this), spender) == 0), - "SafeERC20: approve from non-zero to non-zero allowance" - ); - _callOptionalReturn(token, abi.encodeWithSelector(token.approve.selector, spender, value)); - } - - function safeIncreaseAllowance( - IERC20 token, - address spender, - uint256 value - ) internal { - uint256 newAllowance = token.allowance(address(this), spender) + value; - _callOptionalReturn(token, abi.encodeWithSelector(token.approve.selector, spender, newAllowance)); - } - - function safeDecreaseAllowance( - IERC20 token, - address spender, - uint256 value - ) internal { - unchecked { - uint256 oldAllowance = token.allowance(address(this), spender); - require(oldAllowance >= value, "SafeERC20: decreased allowance below zero"); - uint256 newAllowance = oldAllowance - value; - _callOptionalReturn(token, abi.encodeWithSelector(token.approve.selector, spender, newAllowance)); - } - } - - function safePermit( - IERC20Permit token, - address owner, - address spender, - uint256 value, - uint256 deadline, - uint8 v, - bytes32 r, - bytes32 s - ) internal { - uint256 nonceBefore = token.nonces(owner); - token.permit(owner, spender, value, deadline, v, r, s); - uint256 nonceAfter = token.nonces(owner); - require(nonceAfter == nonceBefore + 1, "SafeERC20: permit did not succeed"); - } - - /** - * @dev Imitates a Solidity high-level call (i.e. a regular function call to a contract), relaxing the requirement - * on the return value: the return value is optional (but if data is returned, it must not be false). - * @param token The token targeted by the call. - * @param data The call data (encoded using abi.encode or one of its variants). - */ - function _callOptionalReturn(IERC20 token, bytes memory data) private { - // We need to perform a low level call here, to bypass Solidity's return data size checking mechanism, since - // we're implementing it ourselves. We use {Address.functionCall} to perform this call, which verifies that - // the target address contains contract code and also asserts for success in the low-level call. - - bytes memory returndata = address(token).functionCall(data, "SafeERC20: low-level call failed"); - if (returndata.length > 0) { - // Return data is optional - require(abi.decode(returndata, (bool)), "SafeERC20: ERC20 operation did not succeed"); - } - } -} - - - - - - - - - - - - - - -/** - * @dev Provides information about the current execution context, including the - * sender of the transaction and its data. While these are generally available - * via msg.sender and msg.data, they should not be accessed in such a direct - * manner, since when dealing with meta-transactions the account sending and - * paying for execution may not be the actual sender (as far as an application - * is concerned). - * - * This contract is only required for intermediate, library-like contracts. - */ -abstract contract Context { - function _msgSender() internal view virtual returns (address) { - return msg.sender; - } - - function _msgData() internal view virtual returns (bytes calldata) { - return msg.data; - } -} - - -/** - * @dev Contract module which provides a basic access control mechanism, where - * there is an account (an owner) that can be granted exclusive access to - * specific functions. - * - * By default, the owner account will be the one that deploys the contract. This - * can later be changed with {transferOwnership}. - * - * This module is used through inheritance. It will make available the modifier - * `onlyOwner`, which can be applied to your functions to restrict their use to - * the owner. - */ -abstract contract Ownable is Context { - address private _owner; - - event OwnershipTransferred(address indexed previousOwner, address indexed newOwner); - - /** - * @dev Initializes the contract setting the deployer as the initial owner. - */ - constructor() { - _transferOwnership(_msgSender()); - } - - /** - * @dev Throws if called by any account other than the owner. - */ - modifier onlyOwner() { - _checkOwner(); - _; - } - - /** - * @dev Returns the address of the current owner. - */ - function owner() public view virtual returns (address) { - return _owner; - } - - /** - * @dev Throws if the sender is not the owner. - */ - function _checkOwner() internal view virtual { - require(owner() == _msgSender(), "Ownable: caller is not the owner"); - } - - /** - * @dev Leaves the contract without owner. It will not be possible to call - * `onlyOwner` functions anymore. Can only be called by the current owner. - * - * NOTE: Renouncing ownership will leave the contract without an owner, - * thereby removing any functionality that is only available to the owner. - */ - function renounceOwnership() public virtual onlyOwner { - _transferOwnership(address(0)); - } - - /** - * @dev Transfers ownership of the contract to a new account (`newOwner`). - * Can only be called by the current owner. - */ - function transferOwnership(address newOwner) public virtual onlyOwner { - require(newOwner != address(0), "Ownable: new owner is the zero address"); - _transferOwnership(newOwner); - } - - /** - * @dev Transfers ownership of the contract to a new account (`newOwner`). - * Internal function without access restriction. - */ - function _transferOwnership(address newOwner) internal virtual { - address oldOwner = _owner; - _owner = newOwner; - emit OwnershipTransferred(oldOwner, newOwner); - } -} - - -contract Operator is Ownable { - address public operator; - uint256 constant baseRate = 10000; - - modifier onlyOperator { - require(msg.sender == owner() || msg.sender == operator, "no permission"); - _; - } - - function setOperator(address operator_) external onlyOwner { - operator = operator_; - } - - - function getCurrTime() external view returns(uint256) { - return block.timestamp; - } - - function getBlockNum() external view returns(uint256) { - return block.number; - } - -} - - - - - -/** - * @dev Library for managing - * https://en.wikipedia.org/wiki/Set_(abstract_data_type)[sets] of primitive - * types. - * - * Sets have the following properties: - * - * - Elements are added, removed, and checked for existence in constant time - * (O(1)). - * - Elements are enumerated in O(n). No guarantees are made on the ordering. - * - * ``` - * contract Example { - * // Add the library methods - * using EnumerableSet for EnumerableSet.AddressSet; - * - * // Declare a set state variable - * EnumerableSet.AddressSet private mySet; - * } - * ``` - * - * As of v3.3.0, sets of type `bytes32` (`Bytes32Set`), `address` (`AddressSet`) - * and `uint256` (`UintSet`) are supported. - * - * [WARNING] - * ==== - * Trying to delete such a structure from storage will likely result in data corruption, rendering the structure unusable. - * See https://github.com/ethereum/solidity/pull/11843[ethereum/solidity#11843] for more info. - * - * In order to clean an EnumerableSet, you can either remove all elements one by one or create a fresh instance using an array of EnumerableSet. - * ==== - */ - -library EnumerableSet { - // To implement this library for multiple types with as little code - // repetition as possible, we write it in terms of a generic Set type with - // bytes32 values. - // The Set implementation uses private functions, and user-facing - // implementations (such as AddressSet) are just wrappers around the - // underlying Set. - // This means that we can only create new EnumerableSets for types that fit - // in bytes32. - - struct Set { - // Storage of set values - bytes32[] _values; - // Position of the value in the `values` array, plus 1 because index 0 - // means a value is not in the set. - mapping(bytes32 => uint256) _indexes; - } - - /** - * @dev Add a value to a set. O(1). - * - * Returns true if the value was added to the set, that is if it was not - * already present. - */ - function _add(Set storage set, bytes32 value) private returns (bool) { - if (!_contains(set, value)) { - set._values.push(value); - // The value is stored at length-1, but we add 1 to all indexes - // and use 0 as a sentinel value - set._indexes[value] = set._values.length; - return true; - } else { - return false; - } - } - - /** - * @dev Removes a value from a set. O(1). - * - * Returns true if the value was removed from the set, that is if it was - * present. - */ - function _remove(Set storage set, bytes32 value) private returns (bool) { - // We read and store the value's index to prevent multiple reads from the same storage slot - uint256 valueIndex = set._indexes[value]; - - if (valueIndex != 0) { - // Equivalent to contains(set, value) - // To delete an element from the _values array in O(1), we swap the element to delete with the last one in - // the array, and then remove the last element (sometimes called as 'swap and pop'). - // This modifies the order of the array, as noted in {at}. - - uint256 toDeleteIndex = valueIndex - 1; - uint256 lastIndex = set._values.length - 1; - - if (lastIndex != toDeleteIndex) { - bytes32 lastValue = set._values[lastIndex]; - - // Move the last value to the index where the value to delete is - set._values[toDeleteIndex] = lastValue; - // Update the index for the moved value - set._indexes[lastValue] = valueIndex; // Replace lastValue's index to valueIndex - } - - // Delete the slot where the moved value was stored - set._values.pop(); - - // Delete the index for the deleted slot - delete set._indexes[value]; - - return true; - } else { - return false; - } - } - - /** - * @dev Returns true if the value is in the set. O(1). - */ - function _contains(Set storage set, bytes32 value) private view returns (bool) { - return set._indexes[value] != 0; - } - - /** - * @dev Returns the number of values on the set. O(1). - */ - function _length(Set storage set) private view returns (uint256) { - return set._values.length; - } - - /** - * @dev Returns the value stored at position `index` in the set. O(1). - * - * Note that there are no guarantees on the ordering of values inside the - * array, and it may change when more values are added or removed. - * - * Requirements: - * - * - `index` must be strictly less than {length}. - */ - function _at(Set storage set, uint256 index) private view returns (bytes32) { - return set._values[index]; - } - - /** - * @dev Return the entire set in an array - * - * WARNING: This operation will copy the entire storage to memory, which can be quite expensive. This is designed - * to mostly be used by view accessors that are queried without any gas fees. Developers should keep in mind that - * this function has an unbounded cost, and using it as part of a state-changing function may render the function - * uncallable if the set grows to a point where copying to memory consumes too much gas to fit in a block. - */ - function _values(Set storage set) private view returns (bytes32[] memory) { - return set._values; - } - - // Bytes32Set - - struct Bytes32Set { - Set _inner; - } - - /** - * @dev Add a value to a set. O(1). - * - * Returns true if the value was added to the set, that is if it was not - * already present. - */ - function add(Bytes32Set storage set, bytes32 value) internal returns (bool) { - return _add(set._inner, value); - } - - /** - * @dev Removes a value from a set. O(1). - * - * Returns true if the value was removed from the set, that is if it was - * present. - */ - function remove(Bytes32Set storage set, bytes32 value) internal returns (bool) { - return _remove(set._inner, value); - } - - /** - * @dev Returns true if the value is in the set. O(1). - */ - function contains(Bytes32Set storage set, bytes32 value) internal view returns (bool) { - return _contains(set._inner, value); - } - - /** - * @dev Returns the number of values in the set. O(1). - */ - function length(Bytes32Set storage set) internal view returns (uint256) { - return _length(set._inner); - } - - /** - * @dev Returns the value stored at position `index` in the set. O(1). - * - * Note that there are no guarantees on the ordering of values inside the - * array, and it may change when more values are added or removed. - * - * Requirements: - * - * - `index` must be strictly less than {length}. - */ - function at(Bytes32Set storage set, uint256 index) internal view returns (bytes32) { - return _at(set._inner, index); - } - - /** - * @dev Return the entire set in an array - * - * WARNING: This operation will copy the entire storage to memory, which can be quite expensive. This is designed - * to mostly be used by view accessors that are queried without any gas fees. Developers should keep in mind that - * this function has an unbounded cost, and using it as part of a state-changing function may render the function - * uncallable if the set grows to a point where copying to memory consumes too much gas to fit in a block. - */ - function values(Bytes32Set storage set) internal view returns (bytes32[] memory) { - return _values(set._inner); - } - - // AddressSet - - struct AddressSet { - Set _inner; - } - - /** - * @dev Add a value to a set. O(1). - * - * Returns true if the value was added to the set, that is if it was not - * already present. - */ - function add(AddressSet storage set, address value) internal returns (bool) { - return _add(set._inner, bytes32(uint256(uint160(value)))); - } - - /** - * @dev Removes a value from a set. O(1). - * - * Returns true if the value was removed from the set, that is if it was - * present. - */ - function remove(AddressSet storage set, address value) internal returns (bool) { - return _remove(set._inner, bytes32(uint256(uint160(value)))); - } - - /** - * @dev Returns true if the value is in the set. O(1). - */ - function contains(AddressSet storage set, address value) internal view returns (bool) { - return _contains(set._inner, bytes32(uint256(uint160(value)))); - } - - /** - * @dev Returns the number of values in the set. O(1). - */ - function length(AddressSet storage set) internal view returns (uint256) { - return _length(set._inner); - } - - /** - * @dev Returns the value stored at position `index` in the set. O(1). - * - * Note that there are no guarantees on the ordering of values inside the - * array, and it may change when more values are added or removed. - * - * Requirements: - * - * - `index` must be strictly less than {length}. - */ - function at(AddressSet storage set, uint256 index) internal view returns (address) { - return address(uint160(uint256(_at(set._inner, index)))); - } - - /** - * @dev Return the entire set in an array - * - * WARNING: This operation will copy the entire storage to memory, which can be quite expensive. This is designed - * to mostly be used by view accessors that are queried without any gas fees. Developers should keep in mind that - * this function has an unbounded cost, and using it as part of a state-changing function may render the function - * uncallable if the set grows to a point where copying to memory consumes too much gas to fit in a block. - */ - function values(AddressSet storage set) internal view returns (address[] memory) { - bytes32[] memory store = _values(set._inner); - address[] memory result; - - /// @solidity memory-safe-assembly - assembly { - result := store - } - - return result; - } - - // UintSet - - struct UintSet { - Set _inner; - } - - /** - * @dev Add a value to a set. O(1). - * - * Returns true if the value was added to the set, that is if it was not - * already present. - */ - function add(UintSet storage set, uint256 value) internal returns (bool) { - return _add(set._inner, bytes32(value)); - } - - /** - * @dev Removes a value from a set. O(1). - * - * Returns true if the value was removed from the set, that is if it was - * present. - */ - function remove(UintSet storage set, uint256 value) internal returns (bool) { - return _remove(set._inner, bytes32(value)); - } - - /** - * @dev Returns true if the value is in the set. O(1). - */ - function contains(UintSet storage set, uint256 value) internal view returns (bool) { - return _contains(set._inner, bytes32(value)); - } - - /** - * @dev Returns the number of values on the set. O(1). - */ - function length(UintSet storage set) internal view returns (uint256) { - return _length(set._inner); - } - - /** - * @dev Returns the value stored at position `index` in the set. O(1). - * - * Note that there are no guarantees on the ordering of values inside the - * array, and it may change when more values are added or removed. - * - * Requirements: - * - * - `index` must be strictly less than {length}. - */ - function at(UintSet storage set, uint256 index) internal view returns (uint256) { - return uint256(_at(set._inner, index)); - } - - /** - * @dev Return the entire set in an array - * - * WARNING: This operation will copy the entire storage to memory, which can be quite expensive. This is designed - * to mostly be used by view accessors that are queried without any gas fees. Developers should keep in mind that - * this function has an unbounded cost, and using it as part of a state-changing function may render the function - * uncallable if the set grows to a point where copying to memory consumes too much gas to fit in a block. - */ - function values(UintSet storage set) internal view returns (uint256[] memory) { - bytes32[] memory store = _values(set._inner); - uint256[] memory result; - - /// @solidity memory-safe-assembly - assembly { - result := store - } - - return result; - } -} - - -contract ActivityPool is Operator { - using SafeMath for uint256; - using SafeERC20 for IERC20; - using EnumerableSet for EnumerableSet.AddressSet; - using EnumerableSet for EnumerableSet.UintSet; - - event AddNewAct(uint256 id); - event Bet(address user, uint256 pID, uint256 bType, uint256 amount, uint256 time); - event SetPrize(uint256 pID, uint256 bType); - event Claim(address user, uint256 pID, uint256 bType, uint256 amount); - event RemovePeriodAct(uint256 pID); - - uint256 public constant muti = 1e18; - uint256 public periodID; - uint256 public betID; - - struct UserInfo { - address user; - uint256 pID; - uint256 amount; - uint256 betTime; - uint256 bType; - uint256 claimAmount; - } - - struct ActInfo { - string name; - string aName; - string bName; - address rewardToken; - uint256 startTime; - uint256 endTime; - uint256 minAmount; - uint256 maxAmount; - uint256 aAmount; - uint256 bAmount; - uint256 winType; - bool isBet; - } - - struct TimeInfo { - uint256 time; - uint256 aAmount; - uint256 bAmount; - } - - struct BestInfo { - address aUser; - address bUser; - uint256 aBet; - uint256 bBet; - } - - mapping(uint256 => BestInfo) bestInfo; - mapping(uint256 => uint256) public timeID; - mapping(uint256 => mapping(uint256 => TimeInfo)) public timeInfo; - mapping(address => mapping(uint256 => uint256)) public userBet; - mapping(uint256 => UserInfo) public betInfo; - mapping(uint256 => uint256) public perAmount; - mapping(uint256 => ActInfo) public actInfo; - mapping(uint256 => mapping(uint256 => string)) public descripName; - - mapping(address => EnumerableSet.UintSet) userPid; - mapping(uint256 => EnumerableSet.AddressSet) aUsers; - mapping(uint256 => EnumerableSet.AddressSet) bUsers; - EnumerableSet.UintSet activePeriod; - EnumerableSet.UintSet removePeriod; - - function addNewAct( - string memory name, - string memory aName, - string memory bName, - address token, - uint256 startTime, - uint256 endTime, - uint256 minAmount, - uint256 maxAmount - ) external onlyOperator { - - checkAdd(msg.sender, startTime, endTime, minAmount, maxAmount); - uint256 id = ++periodID; - actInfo[id].name = name; - actInfo[id].aName = aName; - actInfo[id].bName = bName; - actInfo[id].startTime = startTime; - actInfo[id].endTime = endTime; - actInfo[id].minAmount = minAmount; - actInfo[id].maxAmount = maxAmount; - actInfo[id].rewardToken = token; - descripName[id][1] = aName; - descripName[id][2] = bName; - activePeriod.add(id); - - emit AddNewAct(id); - } - - - function removePeriodAct(uint256 pID) external onlyOperator { - checkRemove(pID); - - activePeriod.remove(pID); - removePeriod.add(pID); - - emit RemovePeriodAct(pID); - } - - - function bet(uint256 pID, uint256 bType, uint256 amount) external payable { - checkBet(msg.sender, pID, bType, amount); - if(actInfo[pID].rewardToken == address(0)) { - require(msg.value == amount, "value err"); - } else { - require(msg.value == 0, "value amount err"); - } - - if(bType == 1) { - if(amount > bestInfo[pID].aBet) { - bestInfo[pID].aUser = msg.sender; - bestInfo[pID].aBet = amount; - } - } else { - if(amount > bestInfo[pID].bBet) { - bestInfo[pID].bUser = msg.sender; - bestInfo[pID].bBet = amount; - } - } - - userPid[msg.sender].add(pID); - uint256 id = ++betID; - userBet[msg.sender][pID] = id; - - if(bType == 1) { - aUsers[pID].add(msg.sender); - actInfo[pID].aAmount = actInfo[pID].aAmount.add(amount); - } else { - bUsers[pID].add(msg.sender); - actInfo[pID].bAmount = actInfo[pID].bAmount.add(amount); - } - - actInfo[pID].isBet = true; - betInfo[id].user = msg.sender; - betInfo[id].pID = pID; - betInfo[id].amount = amount; - betInfo[id].betTime = block.timestamp; - betInfo[id].bType = bType; - - uint256 tID = ++timeID[pID]; - timeInfo[pID][tID].time = block.timestamp; - timeInfo[pID][tID].aAmount = actInfo[pID].aAmount; - timeInfo[pID][tID].bAmount = actInfo[pID].bAmount; - - if(actInfo[pID].rewardToken != address(0)) { - IERC20(actInfo[pID].rewardToken).safeTransferFrom(msg.sender, address(this), amount); - } - emit Bet(msg.sender, pID, bType, amount, betInfo[id].betTime); - } - - function setPrize(uint256 pID, uint256 bType) external onlyOperator { - checkSetPrize(msg.sender, pID, bType); - - if(block.timestamp <= actInfo[pID].startTime) { - actInfo[pID].startTime = block.timestamp; - - } - actInfo[pID].endTime = block.timestamp; - - actInfo[pID].winType = bType; - perAmount[pID] = getPerAmount(pID, bType); - - emit SetPrize(pID, bType); - } - - function recive() public payable {} - - function claim(uint256 pID) external { - uint256 amount = checkClaim(msg.sender, pID); - - uint256 id = userBet[msg.sender][pID]; - betInfo[id].claimAmount = amount; - if(actInfo[pID].rewardToken != address(0)) { - IERC20(actInfo[pID].rewardToken).safeTransfer(msg.sender, amount); - } else { - payable(msg.sender).transfer(amount); - } - - emit Claim(msg.sender, pID, betInfo[id].bType, amount); - } - - function checkClaim(address user, uint256 pID) public view returns(uint256 amount) { - require(userPid[user].contains(pID), "not bet"); - uint256 id = userBet[user][pID]; - require(betInfo[id].user == user, "not user"); - require(actInfo[pID].winType != 0, "not prize"); - require(betInfo[id].claimAmount == 0, "has claim"); - - if(actInfo[pID].winType != 3) { - require(actInfo[pID].winType == betInfo[id].bType, "not right"); - amount = perAmount[pID].mul(betInfo[id].amount).div(muti); - require(amount > 0, "no amount"); - } else { - amount = betInfo[id].amount; - } - - return amount; - } - - function getActualRate( - address user, - uint256 pID, - uint256 bType, - uint256 amount - ) external view returns(uint256, uint256, bool) { - if(bType < 1 || bType > 2 || !activePeriod.contains(pID)) { - return (0, 0, false); - } else if(userBet[user][pID] != 0 || actInfo[pID].winType != 0 || amount == 0) { - (uint256 ra, uint256 rb) = getRate(pID, timeID[pID]); - return (ra, rb, false); - } else { - (uint256 aAmount, uint256 bAmount) = (actInfo[pID].aAmount, actInfo[pID].bAmount); - if(bType == 1) { - aAmount = aAmount.add(amount); - } else { - bAmount = bAmount.add(amount); - } - - uint256 total = aAmount.add(bAmount); - if(bAmount == 0 && aAmount != 0) { - return (muti, 0, true); - } - if(bAmount != 0 && aAmount == 0) { - return (0, muti, true); - } - return (total.mul(muti).div(aAmount), total.mul(muti).div(bAmount), true); - } - } - - function getRate(uint256 pID, uint256 tID) public view returns(uint256, uint256) { - (uint256 aAmount, uint256 bAmount) = (timeInfo[pID][tID].aAmount, timeInfo[pID][tID].bAmount); - uint256 total = aAmount.add(bAmount); - if(total == 0) { - return (0, 0); - } - if(bAmount == 0 && aAmount != 0) { - return (muti, 0); - } - if(bAmount != 0 && aAmount == 0) { - return (0, muti); - } - return (total.mul(muti).div(aAmount), total.mul(muti).div(bAmount)); - } - - function getBestInfo(uint256 pID) - external - view - returns(address aUser, address bUser, uint256 aBet, uint256 bBet, uint256 aReward, uint256 bReward) - { - aUser = bestInfo[pID].aUser; - bUser = bestInfo[pID].bUser; - aBet = bestInfo[pID].aBet; - bBet = bestInfo[pID].bBet; - aReward = getPerAmount(pID, 1).mul(aBet).div(muti); - bReward = getPerAmount(pID, 2).mul(bBet).div(muti); - } - - function getPerAmount(uint256 pID, uint256 bType) public view returns(uint256) { - uint256 total = actInfo[pID].aAmount.add(actInfo[pID].bAmount); - if(total == 0) { - return 0; - } - - if(actInfo[pID].winType == 3) { - return muti; - } - - if(bType == 1) { - if(actInfo[pID].aAmount == 0 || actInfo[pID].winType == 2) { - return 0; - } - return total.mul(muti).div(actInfo[pID].aAmount); - } - - if(bType == 2) { - if(actInfo[pID].bAmount == 0 || actInfo[pID].winType == 1) { - return 0; - } - return total.mul(muti).div(actInfo[pID].bAmount); - } - - return 0; - - } - - function checkSetPrize(address user, uint256 pID, uint256 bType) public view returns(bool) { - require(user == owner() || user == operator, "no permission"); - require(bType > 0 && bType <= 3, "type err"); - require(activePeriod.contains(pID), "not active"); - require(actInfo[pID].winType == 0, "has set"); - - return true; - } - - function checkBet( - address user, - uint256 pID, - uint256 bType, - uint256 amount - ) public view returns(bool) { - require(activePeriod.contains(pID), "not active"); - require(actInfo[pID].startTime <= block.timestamp, "not start"); - require(actInfo[pID].endTime > block.timestamp, "has end"); - require(!userPid[user].contains(pID), "has bet"); - require(bType > 0 && bType < 3, "type err"); - require(amount >= actInfo[pID].minAmount && amount <= actInfo[pID].maxAmount, "amount err"); - if(actInfo[pID].rewardToken != address(0)) { - require(IERC20(actInfo[pID].rewardToken).allowance(user, address(this)) >= amount, "not approve enough"); - require(IERC20(actInfo[pID].rewardToken).balanceOf(user) >= amount, "not enough"); - } else { - require(user.balance >= amount, "main token err"); - } - - return true; - } - - - function checkRemove(uint256 pID) public view returns(bool) { - require(activePeriod.contains(pID), "not in"); - require(!actInfo[pID].isBet, "has bet"); - - return true; - } - - function checkAdd( - address user, - uint256 startTime, - uint256 endTime, - uint256 minAmount, - uint256 maxAmount - ) public view returns(bool) { - require(user == owner() || user == operator, "no permission"); - require(startTime > block.timestamp, "startTime err"); - require(endTime > startTime, "endTime err"); - require(minAmount > 0 && maxAmount > minAmount, "amount err"); - - return true; - } - - function getStatus(uint256 pID) external view returns(uint256) { - if(!removePeriod.contains(pID) && !activePeriod.contains(pID)) { - return 5; - } else if(removePeriod.contains(pID)) { - return 6; - } else if(block.timestamp < actInfo[pID].startTime) { - return 1; - } else if ( - actInfo[pID].startTime <= block.timestamp && - actInfo[pID].endTime > block.timestamp - ) { - return 2; - } else if (actInfo[pID].endTime <= block.timestamp && actInfo[pID].winType == 0){ - return 3; - } else if(actInfo[pID].winType != 0) { - return 4; - } - return 0; - } - - function getUserPidNum(address user) external view returns(uint256) { - return userPid[user].length(); - } - - function getUserPid(address user, uint256 index) external view returns(uint256) { - return userPid[user].at(index); - } - - function getAUsersNum(uint256 pID) external view returns(uint256) { - return aUsers[pID].length(); - } - - function getAUsers(uint256 pID, uint256 index) external view returns(address) { - return aUsers[pID].at(index); - } - - function getBUsersNum(uint256 pID) external view returns(uint256) { - return bUsers[pID].length(); - } - - function getBUsers(uint256 pID, uint256 index) external view returns(address) { - return bUsers[pID].at(index); - } - - function getActivePeriodNum() external view returns(uint256) { - return activePeriod.length(); - } - - function getActivePeriod(uint256 index) external view returns(uint256) { - return activePeriod.at(index); - } - - function getRemovePeriodNum() external view returns(uint256) { - return removePeriod.length(); - } - - function getRemovePeriod(uint256 index) external view returns(uint256) { - return removePeriod.at(index); - } -} \ No newline at end of file diff --git a/app/api/uploads/ActivityPool-1729823113167-316818505.sol b/app/api/uploads/ActivityPool-1729823113167-316818505.sol deleted file mode 100644 index daf3372..0000000 --- a/app/api/uploads/ActivityPool-1729823113167-316818505.sol +++ /dev/null @@ -1,1648 +0,0 @@ -// SPDX-License-Identifier: MIT -// OpenZeppelin Contracts (last updated v4.7.0) (utils/Address.sol) - -pragma solidity ^0.8.1; - -/** - * @dev Collection of functions related to the address type - */ -library Address { - /** - * @dev Returns true if `account` is a contract. - * - * [IMPORTANT] - * ==== - * It is unsafe to assume that an address for which this function returns - * false is an externally-owned account (EOA) and not a contract. - * - * Among others, `isContract` will return false for the following - * types of addresses: - * - * - an externally-owned account - * - a contract in construction - * - an address where a contract will be created - * - an address where a contract lived, but was destroyed - * ==== - * - * [IMPORTANT] - * ==== - * You shouldn't rely on `isContract` to protect against flash loan attacks! - * - * Preventing calls from contracts is highly discouraged. It breaks composability, breaks support for smart wallets - * like Gnosis Safe, and does not provide security since it can be circumvented by calling from a contract - * constructor. - * ==== - */ - function isContract(address account) internal view returns (bool) { - // This method relies on extcodesize/address.code.length, which returns 0 - // for contracts in construction, since the code is only stored at the end - // of the constructor execution. - - return account.code.length > 0; - } - - /** - * @dev Replacement for Solidity's `transfer`: sends `amount` wei to - * `recipient`, forwarding all available gas and reverting on errors. - * - * https://eips.ethereum.org/EIPS/eip-1884[EIP1884] increases the gas cost - * of certain opcodes, possibly making contracts go over the 2300 gas limit - * imposed by `transfer`, making them unable to receive funds via - * `transfer`. {sendValue} removes this limitation. - * - * https://diligence.consensys.net/posts/2019/09/stop-using-soliditys-transfer-now/[Learn more]. - * - * IMPORTANT: because control is transferred to `recipient`, care must be - * taken to not create reentrancy vulnerabilities. Consider using - * {ReentrancyGuard} or the - * https://solidity.readthedocs.io/en/v0.5.11/security-considerations.html#use-the-checks-effects-interactions-pattern[checks-effects-interactions pattern]. - */ - function sendValue(address payable recipient, uint256 amount) internal { - require(address(this).balance >= amount, "Address: insufficient balance"); - - (bool success, ) = recipient.call{value: amount}(""); - require(success, "Address: unable to send value, recipient may have reverted"); - } - - /** - * @dev Performs a Solidity function call using a low level `call`. A - * plain `call` is an unsafe replacement for a function call: use this - * function instead. - * - * If `target` reverts with a revert reason, it is bubbled up by this - * function (like regular Solidity function calls). - * - * Returns the raw returned data. To convert to the expected return value, - * use https://solidity.readthedocs.io/en/latest/units-and-global-variables.html?highlight=abi.decode#abi-encoding-and-decoding-functions[`abi.decode`]. - * - * Requirements: - * - * - `target` must be a contract. - * - calling `target` with `data` must not revert. - * - * _Available since v3.1._ - */ - function functionCall(address target, bytes memory data) internal returns (bytes memory) { - return functionCallWithValue(target, data, 0, "Address: low-level call failed"); - } - - /** - * @dev Same as {xref-Address-functionCall-address-bytes-}[`functionCall`], but with - * `errorMessage` as a fallback revert reason when `target` reverts. - * - * _Available since v3.1._ - */ - function functionCall( - address target, - bytes memory data, - string memory errorMessage - ) internal returns (bytes memory) { - return functionCallWithValue(target, data, 0, errorMessage); - } - - /** - * @dev Same as {xref-Address-functionCall-address-bytes-}[`functionCall`], - * but also transferring `value` wei to `target`. - * - * Requirements: - * - * - the calling contract must have an ETH balance of at least `value`. - * - the called Solidity function must be `payable`. - * - * _Available since v3.1._ - */ - function functionCallWithValue( - address target, - bytes memory data, - uint256 value - ) internal returns (bytes memory) { - return functionCallWithValue(target, data, value, "Address: low-level call with value failed"); - } - - /** - * @dev Same as {xref-Address-functionCallWithValue-address-bytes-uint256-}[`functionCallWithValue`], but - * with `errorMessage` as a fallback revert reason when `target` reverts. - * - * _Available since v3.1._ - */ - function functionCallWithValue( - address target, - bytes memory data, - uint256 value, - string memory errorMessage - ) internal returns (bytes memory) { - require(address(this).balance >= value, "Address: insufficient balance for call"); - (bool success, bytes memory returndata) = target.call{value: value}(data); - return verifyCallResultFromTarget(target, success, returndata, errorMessage); - } - - /** - * @dev Same as {xref-Address-functionCall-address-bytes-}[`functionCall`], - * but performing a static call. - * - * _Available since v3.3._ - */ - function functionStaticCall(address target, bytes memory data) internal view returns (bytes memory) { - return functionStaticCall(target, data, "Address: low-level static call failed"); - } - - /** - * @dev Same as {xref-Address-functionCall-address-bytes-string-}[`functionCall`], - * but performing a static call. - * - * _Available since v3.3._ - */ - function functionStaticCall( - address target, - bytes memory data, - string memory errorMessage - ) internal view returns (bytes memory) { - (bool success, bytes memory returndata) = target.staticcall(data); - return verifyCallResultFromTarget(target, success, returndata, errorMessage); - } - - /** - * @dev Same as {xref-Address-functionCall-address-bytes-}[`functionCall`], - * but performing a delegate call. - * - * _Available since v3.4._ - */ - function functionDelegateCall(address target, bytes memory data) internal returns (bytes memory) { - return functionDelegateCall(target, data, "Address: low-level delegate call failed"); - } - - /** - * @dev Same as {xref-Address-functionCall-address-bytes-string-}[`functionCall`], - * but performing a delegate call. - * - * _Available since v3.4._ - */ - function functionDelegateCall( - address target, - bytes memory data, - string memory errorMessage - ) internal returns (bytes memory) { - (bool success, bytes memory returndata) = target.delegatecall(data); - return verifyCallResultFromTarget(target, success, returndata, errorMessage); - } - - /** - * @dev Tool to verify that a low level call to smart-contract was successful, and revert (either by bubbling - * the revert reason or using the provided one) in case of unsuccessful call or if target was not a contract. - * - * _Available since v4.8._ - */ - function verifyCallResultFromTarget( - address target, - bool success, - bytes memory returndata, - string memory errorMessage - ) internal view returns (bytes memory) { - if (success) { - if (returndata.length == 0) { - // only check isContract if the call was successful and the return data is empty - // otherwise we already know that it was a contract - require(isContract(target), "Address: call to non-contract"); - } - return returndata; - } else { - _revert(returndata, errorMessage); - } - } - - /** - * @dev Tool to verify that a low level call was successful, and revert if it wasn't, either by bubbling the - * revert reason or using the provided one. - * - * _Available since v4.3._ - */ - function verifyCallResult( - bool success, - bytes memory returndata, - string memory errorMessage - ) internal pure returns (bytes memory) { - if (success) { - return returndata; - } else { - _revert(returndata, errorMessage); - } - } - - function _revert(bytes memory returndata, string memory errorMessage) private pure { - // Look for revert reason and bubble it up if present - if (returndata.length > 0) { - // The easiest way to bubble the revert reason is using memory via assembly - /// @solidity memory-safe-assembly - assembly { - let returndata_size := mload(returndata) - revert(add(32, returndata), returndata_size) - } - } else { - revert(errorMessage); - } - } -} - -// OpenZeppelin Contracts (last updated v4.6.0) (token/ERC20/IERC20.sol) - - - -/** - * @dev Interface of the ERC20 standard as defined in the EIP. - */ -interface IERC20 { - /** - * @dev Emitted when `value` tokens are moved from one account (`from`) to - * another (`to`). - * - * Note that `value` may be zero. - */ - event Transfer(address indexed from, address indexed to, uint256 value); - - /** - * @dev Emitted when the allowance of a `spender` for an `owner` is set by - * a call to {approve}. `value` is the new allowance. - */ - event Approval(address indexed owner, address indexed spender, uint256 value); - - /** - * @dev Returns the amount of tokens in existence. - */ - function totalSupply() external view returns (uint256); - - /** - * @dev Returns the amount of tokens owned by `account`. - */ - function balanceOf(address account) external view returns (uint256); - - /** - * @dev Moves `amount` tokens from the caller's account to `to`. - * - * Returns a boolean value indicating whether the operation succeeded. - * - * Emits a {Transfer} event. - */ - function transfer(address to, uint256 amount) external returns (bool); - - /** - * @dev Returns the remaining number of tokens that `spender` will be - * allowed to spend on behalf of `owner` through {transferFrom}. This is - * zero by default. - * - * This value changes when {approve} or {transferFrom} are called. - */ - function allowance(address owner, address spender) external view returns (uint256); - - /** - * @dev Sets `amount` as the allowance of `spender` over the caller's tokens. - * - * Returns a boolean value indicating whether the operation succeeded. - * - * IMPORTANT: Beware that changing an allowance with this method brings the risk - * that someone may use both the old and the new allowance by unfortunate - * transaction ordering. One possible solution to mitigate this race - * condition is to first reduce the spender's allowance to 0 and set the - * desired value afterwards: - * https://github.com/ethereum/EIPs/issues/20#issuecomment-263524729 - * - * Emits an {Approval} event. - */ - function approve(address spender, uint256 amount) external returns (bool); - - /** - * @dev Moves `amount` tokens from `from` to `to` using the - * allowance mechanism. `amount` is then deducted from the caller's - * allowance. - * - * Returns a boolean value indicating whether the operation succeeded. - * - * Emits a {Transfer} event. - */ - function transferFrom( - address from, - address to, - uint256 amount - ) external returns (bool); - - - function mint(address account_, uint256 amount_) external; - - function burn(uint256 amount) external; - -} - - - - - - - - - - - -/** - * @dev Wrappers over Solidity's arithmetic operations with added overflow - * checks. - * - * Arithmetic operations in Solidity wrap on overflow. This can easily result - * in bugs, because programmers usually assume that an overflow raises an - * error, which is the standard behavior in high level programming languages. - * `SafeMath` restores this intuition by reverting the transaction when an - * operation overflows. - * - * Using this library instead of the unchecked operations eliminates an entire - * class of bugs, so it's recommended to use it always. - */ -library SafeMath { - /** - * @dev Returns the addition of two unsigned integers, reverting on - * overflow. - * - * Counterpart to Solidity's `+` operator. - * - * Requirements: - * - * - Addition cannot overflow. - */ - function add(uint256 a, uint256 b) internal pure returns (uint256) { - uint256 c = a + b; - require(c >= a, "SafeMath: addition overflow"); - - return c; - } - - /** - * @dev Returns the subtraction of two unsigned integers, reverting on - * overflow (when the result is negative). - * - * Counterpart to Solidity's `-` operator. - * - * Requirements: - * - * - Subtraction cannot overflow. - */ - function sub(uint256 a, uint256 b) internal pure returns (uint256) { - return sub(a, b, "SafeMath: subtraction overflow"); - } - - /** - * @dev Returns the subtraction of two unsigned integers, reverting with custom message on - * overflow (when the result is negative). - * - * Counterpart to Solidity's `-` operator. - * - * Requirements: - * - * - Subtraction cannot overflow. - */ - function sub( - uint256 a, - uint256 b, - string memory errorMessage - ) internal pure returns (uint256) { - require(b <= a, errorMessage); - uint256 c = a - b; - - return c; - } - - /** - * @dev Returns the multiplication of two unsigned integers, reverting on - * overflow. - * - * Counterpart to Solidity's `*` operator. - * - * Requirements: - * - * - Multiplication cannot overflow. - */ - function mul(uint256 a, uint256 b) internal pure returns (uint256) { - // Gas optimization: this is cheaper than requiring 'a' not being zero, but the - // benefit is lost if 'b' is also tested. - // See: https://github.com/OpenZeppelin/openzeppelin-contracts/pull/522 - if (a == 0) { - return 0; - } - - uint256 c = a * b; - require(c / a == b, "SafeMath: multiplication overflow"); - - return c; - } - - /** - * @dev Returns the integer division of two unsigned integers. Reverts on - * division by zero. The result is rounded towards zero. - * - * Counterpart to Solidity's `/` operator. Note: this function uses a - * `revert` opcode (which leaves remaining gas untouched) while Solidity - * uses an invalid opcode to revert (consuming all remaining gas). - * - * Requirements: - * - * - The divisor cannot be zero. - */ - function div(uint256 a, uint256 b) internal pure returns (uint256) { - return div(a, b, "SafeMath: division by zero"); - } - - /** - * @dev Returns the integer division of two unsigned integers. Reverts with custom message on - * division by zero. The result is rounded towards zero. - * - * Counterpart to Solidity's `/` operator. Note: this function uses a - * `revert` opcode (which leaves remaining gas untouched) while Solidity - * uses an invalid opcode to revert (consuming all remaining gas). - * - * Requirements: - * - * - The divisor cannot be zero. - */ - function div( - uint256 a, - uint256 b, - string memory errorMessage - ) internal pure returns (uint256) { - require(b > 0, errorMessage); - uint256 c = a / b; - // assert(a == b * c + a % b); // There is no case in which this doesn't hold - - return c; - } - - /** - * @dev Returns the remainder of dividing two unsigned integers. (unsigned integer modulo), - * Reverts when dividing by zero. - * - * Counterpart to Solidity's `%` operator. This function uses a `revert` - * opcode (which leaves remaining gas untouched) while Solidity uses an - * invalid opcode to revert (consuming all remaining gas). - * - * Requirements: - * - * - The divisor cannot be zero. - */ - function mod(uint256 a, uint256 b) internal pure returns (uint256) { - return mod(a, b, "SafeMath: modulo by zero"); - } - - /** - * @dev Returns the remainder of dividing two unsigned integers. (unsigned integer modulo), - * Reverts with custom message when dividing by zero. - * - * Counterpart to Solidity's `%` operator. This function uses a `revert` - * opcode (which leaves remaining gas untouched) while Solidity uses an - * invalid opcode to revert (consuming all remaining gas). - * - * Requirements: - * - * - The divisor cannot be zero. - */ - function mod( - uint256 a, - uint256 b, - string memory errorMessage - ) internal pure returns (uint256) { - require(b != 0, errorMessage); - return a % b; - } - - // babylonian method (https://en.wikipedia.org/wiki/Methods_of_computing_square_roots#Babylonian_method) - function sqrrt(uint256 a) internal pure returns (uint256 c) { - if (a > 3) { - c = a; - uint256 b = add(div(a, 2), 1); - while (b < c) { - c = b; - b = div(add(div(a, b), b), 2); - } - } else if (a != 0) { - c = 1; - } - } - - /* - * Expects percentage to be trailed by 00, - */ - function percentageAmount(uint256 total_, uint8 percentage_) internal pure returns (uint256 percentAmount_) { - return div(mul(total_, percentage_), 1000); - } - - /* - * Expects percentage to be trailed by 00, - */ - function substractPercentage(uint256 total_, uint8 percentageToSub_) internal pure returns (uint256 result_) { - return sub(total_, div(mul(total_, percentageToSub_), 1000)); - } - - function percentageOfTotal(uint256 part_, uint256 total_) internal pure returns (uint256 percent_) { - return div(mul(part_, 100), total_); - } - - /** - * Taken from Hypersonic https://github.com/M2629/HyperSonic/blob/main/Math.sol - * @dev Returns the average of two numbers. The result is rounded towards - * zero. - */ - function average(uint256 a, uint256 b) internal pure returns (uint256) { - // (a + b) / 2 can overflow, so we distribute - return (a / 2) + (b / 2) + (((a % 2) + (b % 2)) / 2); - } - - function quadraticPricing(uint256 payment_, uint256 multiplier_) internal pure returns (uint256) { - return sqrrt(mul(multiplier_, payment_)); - } - - function bondingCurve(uint256 supply_, uint256 multiplier_) internal pure returns (uint256) { - return mul(multiplier_, supply_); - } -} - -// OpenZeppelin Contracts (last updated v4.7.0) (token/ERC20/utils/SafeERC20.sol) - - - - - -// OpenZeppelin Contracts v4.4.1 (token/ERC20/extensions/draft-IERC20Permit.sol) - - - -/** - * @dev Interface of the ERC20 Permit extension allowing approvals to be made via signatures, as defined in - * https://eips.ethereum.org/EIPS/eip-2612[EIP-2612]. - * - * Adds the {permit} method, which can be used to change an account's ERC20 allowance (see {IERC20-allowance}) by - * presenting a message signed by the account. By not relying on {IERC20-approve}, the token holder account doesn't - * need to send a transaction, and thus is not required to hold Ether at all. - */ -interface IERC20Permit { - /** - * @dev Sets `value` as the allowance of `spender` over ``owner``'s tokens, - * given ``owner``'s signed approval. - * - * IMPORTANT: The same issues {IERC20-approve} has related to transaction - * ordering also apply here. - * - * Emits an {Approval} event. - * - * Requirements: - * - * - `spender` cannot be the zero address. - * - `deadline` must be a timestamp in the future. - * - `v`, `r` and `s` must be a valid `secp256k1` signature from `owner` - * over the EIP712-formatted function arguments. - * - the signature must use ``owner``'s current nonce (see {nonces}). - * - * For more information on the signature format, see the - * https://eips.ethereum.org/EIPS/eip-2612#specification[relevant EIP - * section]. - */ - function permit( - address owner, - address spender, - uint256 value, - uint256 deadline, - uint8 v, - bytes32 r, - bytes32 s - ) external; - - /** - * @dev Returns the current nonce for `owner`. This value must be - * included whenever a signature is generated for {permit}. - * - * Every successful call to {permit} increases ``owner``'s nonce by one. This - * prevents a signature from being used multiple times. - */ - function nonces(address owner) external view returns (uint256); - - /** - * @dev Returns the domain separator used in the encoding of the signature for {permit}, as defined by {EIP712}. - */ - // solhint-disable-next-line func-name-mixedcase - function DOMAIN_SEPARATOR() external view returns (bytes32); -} - - - -/** - * @title SafeERC20 - * @dev Wrappers around ERC20 operations that throw on failure (when the token - * contract returns false). Tokens that return no value (and instead revert or - * throw on failure) are also supported, non-reverting calls are assumed to be - * successful. - * To use this library you can add a `using SafeERC20 for IERC20;` statement to your contract, - * which allows you to call the safe operations as `token.safeTransfer(...)`, etc. - */ -library SafeERC20 { - using Address for address; - - function safeTransfer( - IERC20 token, - address to, - uint256 value - ) internal { - _callOptionalReturn(token, abi.encodeWithSelector(token.transfer.selector, to, value)); - } - - function safeTransferFrom( - IERC20 token, - address from, - address to, - uint256 value - ) internal { - _callOptionalReturn(token, abi.encodeWithSelector(token.transferFrom.selector, from, to, value)); - } - - /** - * @dev Deprecated. This function has issues similar to the ones found in - * {IERC20-approve}, and its usage is discouraged. - * - * Whenever possible, use {safeIncreaseAllowance} and - * {safeDecreaseAllowance} instead. - */ - function safeApprove( - IERC20 token, - address spender, - uint256 value - ) internal { - // safeApprove should only be called when setting an initial allowance, - // or when resetting it to zero. To increase and decrease it, use - // 'safeIncreaseAllowance' and 'safeDecreaseAllowance' - require( - (value == 0) || (token.allowance(address(this), spender) == 0), - "SafeERC20: approve from non-zero to non-zero allowance" - ); - _callOptionalReturn(token, abi.encodeWithSelector(token.approve.selector, spender, value)); - } - - function safeIncreaseAllowance( - IERC20 token, - address spender, - uint256 value - ) internal { - uint256 newAllowance = token.allowance(address(this), spender) + value; - _callOptionalReturn(token, abi.encodeWithSelector(token.approve.selector, spender, newAllowance)); - } - - function safeDecreaseAllowance( - IERC20 token, - address spender, - uint256 value - ) internal { - unchecked { - uint256 oldAllowance = token.allowance(address(this), spender); - require(oldAllowance >= value, "SafeERC20: decreased allowance below zero"); - uint256 newAllowance = oldAllowance - value; - _callOptionalReturn(token, abi.encodeWithSelector(token.approve.selector, spender, newAllowance)); - } - } - - function safePermit( - IERC20Permit token, - address owner, - address spender, - uint256 value, - uint256 deadline, - uint8 v, - bytes32 r, - bytes32 s - ) internal { - uint256 nonceBefore = token.nonces(owner); - token.permit(owner, spender, value, deadline, v, r, s); - uint256 nonceAfter = token.nonces(owner); - require(nonceAfter == nonceBefore + 1, "SafeERC20: permit did not succeed"); - } - - /** - * @dev Imitates a Solidity high-level call (i.e. a regular function call to a contract), relaxing the requirement - * on the return value: the return value is optional (but if data is returned, it must not be false). - * @param token The token targeted by the call. - * @param data The call data (encoded using abi.encode or one of its variants). - */ - function _callOptionalReturn(IERC20 token, bytes memory data) private { - // We need to perform a low level call here, to bypass Solidity's return data size checking mechanism, since - // we're implementing it ourselves. We use {Address.functionCall} to perform this call, which verifies that - // the target address contains contract code and also asserts for success in the low-level call. - - bytes memory returndata = address(token).functionCall(data, "SafeERC20: low-level call failed"); - if (returndata.length > 0) { - // Return data is optional - require(abi.decode(returndata, (bool)), "SafeERC20: ERC20 operation did not succeed"); - } - } -} - - - - - - - - - - - - - - -/** - * @dev Provides information about the current execution context, including the - * sender of the transaction and its data. While these are generally available - * via msg.sender and msg.data, they should not be accessed in such a direct - * manner, since when dealing with meta-transactions the account sending and - * paying for execution may not be the actual sender (as far as an application - * is concerned). - * - * This contract is only required for intermediate, library-like contracts. - */ -abstract contract Context { - function _msgSender() internal view virtual returns (address) { - return msg.sender; - } - - function _msgData() internal view virtual returns (bytes calldata) { - return msg.data; - } -} - - -/** - * @dev Contract module which provides a basic access control mechanism, where - * there is an account (an owner) that can be granted exclusive access to - * specific functions. - * - * By default, the owner account will be the one that deploys the contract. This - * can later be changed with {transferOwnership}. - * - * This module is used through inheritance. It will make available the modifier - * `onlyOwner`, which can be applied to your functions to restrict their use to - * the owner. - */ -abstract contract Ownable is Context { - address private _owner; - - event OwnershipTransferred(address indexed previousOwner, address indexed newOwner); - - /** - * @dev Initializes the contract setting the deployer as the initial owner. - */ - constructor() { - _transferOwnership(_msgSender()); - } - - /** - * @dev Throws if called by any account other than the owner. - */ - modifier onlyOwner() { - _checkOwner(); - _; - } - - /** - * @dev Returns the address of the current owner. - */ - function owner() public view virtual returns (address) { - return _owner; - } - - /** - * @dev Throws if the sender is not the owner. - */ - function _checkOwner() internal view virtual { - require(owner() == _msgSender(), "Ownable: caller is not the owner"); - } - - /** - * @dev Leaves the contract without owner. It will not be possible to call - * `onlyOwner` functions anymore. Can only be called by the current owner. - * - * NOTE: Renouncing ownership will leave the contract without an owner, - * thereby removing any functionality that is only available to the owner. - */ - function renounceOwnership() public virtual onlyOwner { - _transferOwnership(address(0)); - } - - /** - * @dev Transfers ownership of the contract to a new account (`newOwner`). - * Can only be called by the current owner. - */ - function transferOwnership(address newOwner) public virtual onlyOwner { - require(newOwner != address(0), "Ownable: new owner is the zero address"); - _transferOwnership(newOwner); - } - - /** - * @dev Transfers ownership of the contract to a new account (`newOwner`). - * Internal function without access restriction. - */ - function _transferOwnership(address newOwner) internal virtual { - address oldOwner = _owner; - _owner = newOwner; - emit OwnershipTransferred(oldOwner, newOwner); - } -} - - -contract Operator is Ownable { - address public operator; - uint256 constant baseRate = 10000; - - modifier onlyOperator { - require(msg.sender == owner() || msg.sender == operator, "no permission"); - _; - } - - function setOperator(address operator_) external onlyOwner { - operator = operator_; - } - - - function getCurrTime() external view returns(uint256) { - return block.timestamp; - } - - function getBlockNum() external view returns(uint256) { - return block.number; - } - -} - - - - - -/** - * @dev Library for managing - * https://en.wikipedia.org/wiki/Set_(abstract_data_type)[sets] of primitive - * types. - * - * Sets have the following properties: - * - * - Elements are added, removed, and checked for existence in constant time - * (O(1)). - * - Elements are enumerated in O(n). No guarantees are made on the ordering. - * - * ``` - * contract Example { - * // Add the library methods - * using EnumerableSet for EnumerableSet.AddressSet; - * - * // Declare a set state variable - * EnumerableSet.AddressSet private mySet; - * } - * ``` - * - * As of v3.3.0, sets of type `bytes32` (`Bytes32Set`), `address` (`AddressSet`) - * and `uint256` (`UintSet`) are supported. - * - * [WARNING] - * ==== - * Trying to delete such a structure from storage will likely result in data corruption, rendering the structure unusable. - * See https://github.com/ethereum/solidity/pull/11843[ethereum/solidity#11843] for more info. - * - * In order to clean an EnumerableSet, you can either remove all elements one by one or create a fresh instance using an array of EnumerableSet. - * ==== - */ - -library EnumerableSet { - // To implement this library for multiple types with as little code - // repetition as possible, we write it in terms of a generic Set type with - // bytes32 values. - // The Set implementation uses private functions, and user-facing - // implementations (such as AddressSet) are just wrappers around the - // underlying Set. - // This means that we can only create new EnumerableSets for types that fit - // in bytes32. - - struct Set { - // Storage of set values - bytes32[] _values; - // Position of the value in the `values` array, plus 1 because index 0 - // means a value is not in the set. - mapping(bytes32 => uint256) _indexes; - } - - /** - * @dev Add a value to a set. O(1). - * - * Returns true if the value was added to the set, that is if it was not - * already present. - */ - function _add(Set storage set, bytes32 value) private returns (bool) { - if (!_contains(set, value)) { - set._values.push(value); - // The value is stored at length-1, but we add 1 to all indexes - // and use 0 as a sentinel value - set._indexes[value] = set._values.length; - return true; - } else { - return false; - } - } - - /** - * @dev Removes a value from a set. O(1). - * - * Returns true if the value was removed from the set, that is if it was - * present. - */ - function _remove(Set storage set, bytes32 value) private returns (bool) { - // We read and store the value's index to prevent multiple reads from the same storage slot - uint256 valueIndex = set._indexes[value]; - - if (valueIndex != 0) { - // Equivalent to contains(set, value) - // To delete an element from the _values array in O(1), we swap the element to delete with the last one in - // the array, and then remove the last element (sometimes called as 'swap and pop'). - // This modifies the order of the array, as noted in {at}. - - uint256 toDeleteIndex = valueIndex - 1; - uint256 lastIndex = set._values.length - 1; - - if (lastIndex != toDeleteIndex) { - bytes32 lastValue = set._values[lastIndex]; - - // Move the last value to the index where the value to delete is - set._values[toDeleteIndex] = lastValue; - // Update the index for the moved value - set._indexes[lastValue] = valueIndex; // Replace lastValue's index to valueIndex - } - - // Delete the slot where the moved value was stored - set._values.pop(); - - // Delete the index for the deleted slot - delete set._indexes[value]; - - return true; - } else { - return false; - } - } - - /** - * @dev Returns true if the value is in the set. O(1). - */ - function _contains(Set storage set, bytes32 value) private view returns (bool) { - return set._indexes[value] != 0; - } - - /** - * @dev Returns the number of values on the set. O(1). - */ - function _length(Set storage set) private view returns (uint256) { - return set._values.length; - } - - /** - * @dev Returns the value stored at position `index` in the set. O(1). - * - * Note that there are no guarantees on the ordering of values inside the - * array, and it may change when more values are added or removed. - * - * Requirements: - * - * - `index` must be strictly less than {length}. - */ - function _at(Set storage set, uint256 index) private view returns (bytes32) { - return set._values[index]; - } - - /** - * @dev Return the entire set in an array - * - * WARNING: This operation will copy the entire storage to memory, which can be quite expensive. This is designed - * to mostly be used by view accessors that are queried without any gas fees. Developers should keep in mind that - * this function has an unbounded cost, and using it as part of a state-changing function may render the function - * uncallable if the set grows to a point where copying to memory consumes too much gas to fit in a block. - */ - function _values(Set storage set) private view returns (bytes32[] memory) { - return set._values; - } - - // Bytes32Set - - struct Bytes32Set { - Set _inner; - } - - /** - * @dev Add a value to a set. O(1). - * - * Returns true if the value was added to the set, that is if it was not - * already present. - */ - function add(Bytes32Set storage set, bytes32 value) internal returns (bool) { - return _add(set._inner, value); - } - - /** - * @dev Removes a value from a set. O(1). - * - * Returns true if the value was removed from the set, that is if it was - * present. - */ - function remove(Bytes32Set storage set, bytes32 value) internal returns (bool) { - return _remove(set._inner, value); - } - - /** - * @dev Returns true if the value is in the set. O(1). - */ - function contains(Bytes32Set storage set, bytes32 value) internal view returns (bool) { - return _contains(set._inner, value); - } - - /** - * @dev Returns the number of values in the set. O(1). - */ - function length(Bytes32Set storage set) internal view returns (uint256) { - return _length(set._inner); - } - - /** - * @dev Returns the value stored at position `index` in the set. O(1). - * - * Note that there are no guarantees on the ordering of values inside the - * array, and it may change when more values are added or removed. - * - * Requirements: - * - * - `index` must be strictly less than {length}. - */ - function at(Bytes32Set storage set, uint256 index) internal view returns (bytes32) { - return _at(set._inner, index); - } - - /** - * @dev Return the entire set in an array - * - * WARNING: This operation will copy the entire storage to memory, which can be quite expensive. This is designed - * to mostly be used by view accessors that are queried without any gas fees. Developers should keep in mind that - * this function has an unbounded cost, and using it as part of a state-changing function may render the function - * uncallable if the set grows to a point where copying to memory consumes too much gas to fit in a block. - */ - function values(Bytes32Set storage set) internal view returns (bytes32[] memory) { - return _values(set._inner); - } - - // AddressSet - - struct AddressSet { - Set _inner; - } - - /** - * @dev Add a value to a set. O(1). - * - * Returns true if the value was added to the set, that is if it was not - * already present. - */ - function add(AddressSet storage set, address value) internal returns (bool) { - return _add(set._inner, bytes32(uint256(uint160(value)))); - } - - /** - * @dev Removes a value from a set. O(1). - * - * Returns true if the value was removed from the set, that is if it was - * present. - */ - function remove(AddressSet storage set, address value) internal returns (bool) { - return _remove(set._inner, bytes32(uint256(uint160(value)))); - } - - /** - * @dev Returns true if the value is in the set. O(1). - */ - function contains(AddressSet storage set, address value) internal view returns (bool) { - return _contains(set._inner, bytes32(uint256(uint160(value)))); - } - - /** - * @dev Returns the number of values in the set. O(1). - */ - function length(AddressSet storage set) internal view returns (uint256) { - return _length(set._inner); - } - - /** - * @dev Returns the value stored at position `index` in the set. O(1). - * - * Note that there are no guarantees on the ordering of values inside the - * array, and it may change when more values are added or removed. - * - * Requirements: - * - * - `index` must be strictly less than {length}. - */ - function at(AddressSet storage set, uint256 index) internal view returns (address) { - return address(uint160(uint256(_at(set._inner, index)))); - } - - /** - * @dev Return the entire set in an array - * - * WARNING: This operation will copy the entire storage to memory, which can be quite expensive. This is designed - * to mostly be used by view accessors that are queried without any gas fees. Developers should keep in mind that - * this function has an unbounded cost, and using it as part of a state-changing function may render the function - * uncallable if the set grows to a point where copying to memory consumes too much gas to fit in a block. - */ - function values(AddressSet storage set) internal view returns (address[] memory) { - bytes32[] memory store = _values(set._inner); - address[] memory result; - - /// @solidity memory-safe-assembly - assembly { - result := store - } - - return result; - } - - // UintSet - - struct UintSet { - Set _inner; - } - - /** - * @dev Add a value to a set. O(1). - * - * Returns true if the value was added to the set, that is if it was not - * already present. - */ - function add(UintSet storage set, uint256 value) internal returns (bool) { - return _add(set._inner, bytes32(value)); - } - - /** - * @dev Removes a value from a set. O(1). - * - * Returns true if the value was removed from the set, that is if it was - * present. - */ - function remove(UintSet storage set, uint256 value) internal returns (bool) { - return _remove(set._inner, bytes32(value)); - } - - /** - * @dev Returns true if the value is in the set. O(1). - */ - function contains(UintSet storage set, uint256 value) internal view returns (bool) { - return _contains(set._inner, bytes32(value)); - } - - /** - * @dev Returns the number of values on the set. O(1). - */ - function length(UintSet storage set) internal view returns (uint256) { - return _length(set._inner); - } - - /** - * @dev Returns the value stored at position `index` in the set. O(1). - * - * Note that there are no guarantees on the ordering of values inside the - * array, and it may change when more values are added or removed. - * - * Requirements: - * - * - `index` must be strictly less than {length}. - */ - function at(UintSet storage set, uint256 index) internal view returns (uint256) { - return uint256(_at(set._inner, index)); - } - - /** - * @dev Return the entire set in an array - * - * WARNING: This operation will copy the entire storage to memory, which can be quite expensive. This is designed - * to mostly be used by view accessors that are queried without any gas fees. Developers should keep in mind that - * this function has an unbounded cost, and using it as part of a state-changing function may render the function - * uncallable if the set grows to a point where copying to memory consumes too much gas to fit in a block. - */ - function values(UintSet storage set) internal view returns (uint256[] memory) { - bytes32[] memory store = _values(set._inner); - uint256[] memory result; - - /// @solidity memory-safe-assembly - assembly { - result := store - } - - return result; - } -} - - -contract ActivityPool is Operator { - using SafeMath for uint256; - using SafeERC20 for IERC20; - using EnumerableSet for EnumerableSet.AddressSet; - using EnumerableSet for EnumerableSet.UintSet; - - event AddNewAct(uint256 id); - event Bet(address user, uint256 pID, uint256 bType, uint256 amount, uint256 time); - event SetPrize(uint256 pID, uint256 bType); - event Claim(address user, uint256 pID, uint256 bType, uint256 amount); - event RemovePeriodAct(uint256 pID); - - uint256 public constant muti = 1e18; - uint256 public periodID; - uint256 public betID; - - struct UserInfo { - address user; - uint256 pID; - uint256 amount; - uint256 betTime; - uint256 bType; - uint256 claimAmount; - } - - struct ActInfo { - string name; - string aName; - string bName; - address rewardToken; - uint256 startTime; - uint256 endTime; - uint256 minAmount; - uint256 maxAmount; - uint256 aAmount; - uint256 bAmount; - uint256 winType; - bool isBet; - } - - struct TimeInfo { - uint256 time; - uint256 aAmount; - uint256 bAmount; - } - - struct BestInfo { - address aUser; - address bUser; - uint256 aBet; - uint256 bBet; - } - - mapping(uint256 => BestInfo) bestInfo; - mapping(uint256 => uint256) public timeID; - mapping(uint256 => mapping(uint256 => TimeInfo)) public timeInfo; - mapping(address => mapping(uint256 => uint256)) public userBet; - mapping(uint256 => UserInfo) public betInfo; - mapping(uint256 => uint256) public perAmount; - mapping(uint256 => ActInfo) public actInfo; - mapping(uint256 => mapping(uint256 => string)) public descripName; - - mapping(address => EnumerableSet.UintSet) userPid; - mapping(uint256 => EnumerableSet.AddressSet) aUsers; - mapping(uint256 => EnumerableSet.AddressSet) bUsers; - EnumerableSet.UintSet activePeriod; - EnumerableSet.UintSet removePeriod; - - function addNewAct( - string memory name, - string memory aName, - string memory bName, - address token, - uint256 startTime, - uint256 endTime, - uint256 minAmount, - uint256 maxAmount - ) external onlyOperator { - - checkAdd(msg.sender, startTime, endTime, minAmount, maxAmount); - uint256 id = ++periodID; - actInfo[id].name = name; - actInfo[id].aName = aName; - actInfo[id].bName = bName; - actInfo[id].startTime = startTime; - actInfo[id].endTime = endTime; - actInfo[id].minAmount = minAmount; - actInfo[id].maxAmount = maxAmount; - actInfo[id].rewardToken = token; - descripName[id][1] = aName; - descripName[id][2] = bName; - activePeriod.add(id); - - emit AddNewAct(id); - } - - - function removePeriodAct(uint256 pID) external onlyOperator { - checkRemove(pID); - - activePeriod.remove(pID); - removePeriod.add(pID); - - emit RemovePeriodAct(pID); - } - - - function bet(uint256 pID, uint256 bType, uint256 amount) external payable { - checkBet(msg.sender, pID, bType, amount); - if(actInfo[pID].rewardToken == address(0)) { - require(msg.value == amount, "value err"); - } else { - require(msg.value == 0, "value amount err"); - } - - if(bType == 1) { - if(amount > bestInfo[pID].aBet) { - bestInfo[pID].aUser = msg.sender; - bestInfo[pID].aBet = amount; - } - } else { - if(amount > bestInfo[pID].bBet) { - bestInfo[pID].bUser = msg.sender; - bestInfo[pID].bBet = amount; - } - } - - userPid[msg.sender].add(pID); - uint256 id = ++betID; - userBet[msg.sender][pID] = id; - - if(bType == 1) { - aUsers[pID].add(msg.sender); - actInfo[pID].aAmount = actInfo[pID].aAmount.add(amount); - } else { - bUsers[pID].add(msg.sender); - actInfo[pID].bAmount = actInfo[pID].bAmount.add(amount); - } - - actInfo[pID].isBet = true; - betInfo[id].user = msg.sender; - betInfo[id].pID = pID; - betInfo[id].amount = amount; - betInfo[id].betTime = block.timestamp; - betInfo[id].bType = bType; - - uint256 tID = ++timeID[pID]; - timeInfo[pID][tID].time = block.timestamp; - timeInfo[pID][tID].aAmount = actInfo[pID].aAmount; - timeInfo[pID][tID].bAmount = actInfo[pID].bAmount; - - if(actInfo[pID].rewardToken != address(0)) { - IERC20(actInfo[pID].rewardToken).safeTransferFrom(msg.sender, address(this), amount); - } - emit Bet(msg.sender, pID, bType, amount, betInfo[id].betTime); - } - - function setPrize(uint256 pID, uint256 bType) external onlyOperator { - checkSetPrize(msg.sender, pID, bType); - - if(block.timestamp <= actInfo[pID].startTime) { - actInfo[pID].startTime = block.timestamp; - - } - actInfo[pID].endTime = block.timestamp; - - actInfo[pID].winType = bType; - perAmount[pID] = getPerAmount(pID, bType); - - emit SetPrize(pID, bType); - } - - function recive() public payable {} - - function claim(uint256 pID) external { - uint256 amount = checkClaim(msg.sender, pID); - - uint256 id = userBet[msg.sender][pID]; - betInfo[id].claimAmount = amount; - if(actInfo[pID].rewardToken != address(0)) { - IERC20(actInfo[pID].rewardToken).safeTransfer(msg.sender, amount); - } else { - payable(msg.sender).transfer(amount); - } - - emit Claim(msg.sender, pID, betInfo[id].bType, amount); - } - - function checkClaim(address user, uint256 pID) public view returns(uint256 amount) { - require(userPid[user].contains(pID), "not bet"); - uint256 id = userBet[user][pID]; - require(betInfo[id].user == user, "not user"); - require(actInfo[pID].winType != 0, "not prize"); - require(betInfo[id].claimAmount == 0, "has claim"); - - if(actInfo[pID].winType != 3) { - require(actInfo[pID].winType == betInfo[id].bType, "not right"); - amount = perAmount[pID].mul(betInfo[id].amount).div(muti); - require(amount > 0, "no amount"); - } else { - amount = betInfo[id].amount; - } - - return amount; - } - - function getActualRate( - address user, - uint256 pID, - uint256 bType, - uint256 amount - ) external view returns(uint256, uint256, bool) { - if(bType < 1 || bType > 2 || !activePeriod.contains(pID)) { - return (0, 0, false); - } else if(userBet[user][pID] != 0 || actInfo[pID].winType != 0 || amount == 0) { - (uint256 ra, uint256 rb) = getRate(pID, timeID[pID]); - return (ra, rb, false); - } else { - (uint256 aAmount, uint256 bAmount) = (actInfo[pID].aAmount, actInfo[pID].bAmount); - if(bType == 1) { - aAmount = aAmount.add(amount); - } else { - bAmount = bAmount.add(amount); - } - - uint256 total = aAmount.add(bAmount); - if(bAmount == 0 && aAmount != 0) { - return (muti, 0, true); - } - if(bAmount != 0 && aAmount == 0) { - return (0, muti, true); - } - return (total.mul(muti).div(aAmount), total.mul(muti).div(bAmount), true); - } - } - - function getRate(uint256 pID, uint256 tID) public view returns(uint256, uint256) { - (uint256 aAmount, uint256 bAmount) = (timeInfo[pID][tID].aAmount, timeInfo[pID][tID].bAmount); - uint256 total = aAmount.add(bAmount); - if(total == 0) { - return (0, 0); - } - if(bAmount == 0 && aAmount != 0) { - return (muti, 0); - } - if(bAmount != 0 && aAmount == 0) { - return (0, muti); - } - return (total.mul(muti).div(aAmount), total.mul(muti).div(bAmount)); - } - - function getBestInfo(uint256 pID) - external - view - returns(address aUser, address bUser, uint256 aBet, uint256 bBet, uint256 aReward, uint256 bReward) - { - aUser = bestInfo[pID].aUser; - bUser = bestInfo[pID].bUser; - aBet = bestInfo[pID].aBet; - bBet = bestInfo[pID].bBet; - aReward = getPerAmount(pID, 1).mul(aBet).div(muti); - bReward = getPerAmount(pID, 2).mul(bBet).div(muti); - } - - function getPerAmount(uint256 pID, uint256 bType) public view returns(uint256) { - uint256 total = actInfo[pID].aAmount.add(actInfo[pID].bAmount); - if(total == 0) { - return 0; - } - - if(actInfo[pID].winType == 3) { - return muti; - } - - if(bType == 1) { - if(actInfo[pID].aAmount == 0 || actInfo[pID].winType == 2) { - return 0; - } - return total.mul(muti).div(actInfo[pID].aAmount); - } - - if(bType == 2) { - if(actInfo[pID].bAmount == 0 || actInfo[pID].winType == 1) { - return 0; - } - return total.mul(muti).div(actInfo[pID].bAmount); - } - - return 0; - - } - - function checkSetPrize(address user, uint256 pID, uint256 bType) public view returns(bool) { - require(user == owner() || user == operator, "no permission"); - require(bType > 0 && bType <= 3, "type err"); - require(activePeriod.contains(pID), "not active"); - require(actInfo[pID].winType == 0, "has set"); - - return true; - } - - function checkBet( - address user, - uint256 pID, - uint256 bType, - uint256 amount - ) public view returns(bool) { - require(activePeriod.contains(pID), "not active"); - require(actInfo[pID].startTime <= block.timestamp, "not start"); - require(actInfo[pID].endTime > block.timestamp, "has end"); - require(!userPid[user].contains(pID), "has bet"); - require(bType > 0 && bType < 3, "type err"); - require(amount >= actInfo[pID].minAmount && amount <= actInfo[pID].maxAmount, "amount err"); - if(actInfo[pID].rewardToken != address(0)) { - require(IERC20(actInfo[pID].rewardToken).allowance(user, address(this)) >= amount, "not approve enough"); - require(IERC20(actInfo[pID].rewardToken).balanceOf(user) >= amount, "not enough"); - } else { - require(user.balance >= amount, "main token err"); - } - - return true; - } - - - function checkRemove(uint256 pID) public view returns(bool) { - require(activePeriod.contains(pID), "not in"); - require(!actInfo[pID].isBet, "has bet"); - - return true; - } - - function checkAdd( - address user, - uint256 startTime, - uint256 endTime, - uint256 minAmount, - uint256 maxAmount - ) public view returns(bool) { - require(user == owner() || user == operator, "no permission"); - require(startTime > block.timestamp, "startTime err"); - require(endTime > startTime, "endTime err"); - require(minAmount > 0 && maxAmount > minAmount, "amount err"); - - return true; - } - - function getStatus(uint256 pID) external view returns(uint256) { - if(!removePeriod.contains(pID) && !activePeriod.contains(pID)) { - return 5; - } else if(removePeriod.contains(pID)) { - return 6; - } else if(block.timestamp < actInfo[pID].startTime) { - return 1; - } else if ( - actInfo[pID].startTime <= block.timestamp && - actInfo[pID].endTime > block.timestamp - ) { - return 2; - } else if (actInfo[pID].endTime <= block.timestamp && actInfo[pID].winType == 0){ - return 3; - } else if(actInfo[pID].winType != 0) { - return 4; - } - return 0; - } - - function getUserPidNum(address user) external view returns(uint256) { - return userPid[user].length(); - } - - function getUserPid(address user, uint256 index) external view returns(uint256) { - return userPid[user].at(index); - } - - function getAUsersNum(uint256 pID) external view returns(uint256) { - return aUsers[pID].length(); - } - - function getAUsers(uint256 pID, uint256 index) external view returns(address) { - return aUsers[pID].at(index); - } - - function getBUsersNum(uint256 pID) external view returns(uint256) { - return bUsers[pID].length(); - } - - function getBUsers(uint256 pID, uint256 index) external view returns(address) { - return bUsers[pID].at(index); - } - - function getActivePeriodNum() external view returns(uint256) { - return activePeriod.length(); - } - - function getActivePeriod(uint256 index) external view returns(uint256) { - return activePeriod.at(index); - } - - function getRemovePeriodNum() external view returns(uint256) { - return removePeriod.length(); - } - - function getRemovePeriod(uint256 index) external view returns(uint256) { - return removePeriod.at(index); - } -} \ No newline at end of file diff --git a/app/api/uploads/ActivityPool-1729823400774-680295923.sol b/app/api/uploads/ActivityPool-1729823400774-680295923.sol deleted file mode 100644 index daf3372..0000000 --- a/app/api/uploads/ActivityPool-1729823400774-680295923.sol +++ /dev/null @@ -1,1648 +0,0 @@ -// SPDX-License-Identifier: MIT -// OpenZeppelin Contracts (last updated v4.7.0) (utils/Address.sol) - -pragma solidity ^0.8.1; - -/** - * @dev Collection of functions related to the address type - */ -library Address { - /** - * @dev Returns true if `account` is a contract. - * - * [IMPORTANT] - * ==== - * It is unsafe to assume that an address for which this function returns - * false is an externally-owned account (EOA) and not a contract. - * - * Among others, `isContract` will return false for the following - * types of addresses: - * - * - an externally-owned account - * - a contract in construction - * - an address where a contract will be created - * - an address where a contract lived, but was destroyed - * ==== - * - * [IMPORTANT] - * ==== - * You shouldn't rely on `isContract` to protect against flash loan attacks! - * - * Preventing calls from contracts is highly discouraged. It breaks composability, breaks support for smart wallets - * like Gnosis Safe, and does not provide security since it can be circumvented by calling from a contract - * constructor. - * ==== - */ - function isContract(address account) internal view returns (bool) { - // This method relies on extcodesize/address.code.length, which returns 0 - // for contracts in construction, since the code is only stored at the end - // of the constructor execution. - - return account.code.length > 0; - } - - /** - * @dev Replacement for Solidity's `transfer`: sends `amount` wei to - * `recipient`, forwarding all available gas and reverting on errors. - * - * https://eips.ethereum.org/EIPS/eip-1884[EIP1884] increases the gas cost - * of certain opcodes, possibly making contracts go over the 2300 gas limit - * imposed by `transfer`, making them unable to receive funds via - * `transfer`. {sendValue} removes this limitation. - * - * https://diligence.consensys.net/posts/2019/09/stop-using-soliditys-transfer-now/[Learn more]. - * - * IMPORTANT: because control is transferred to `recipient`, care must be - * taken to not create reentrancy vulnerabilities. Consider using - * {ReentrancyGuard} or the - * https://solidity.readthedocs.io/en/v0.5.11/security-considerations.html#use-the-checks-effects-interactions-pattern[checks-effects-interactions pattern]. - */ - function sendValue(address payable recipient, uint256 amount) internal { - require(address(this).balance >= amount, "Address: insufficient balance"); - - (bool success, ) = recipient.call{value: amount}(""); - require(success, "Address: unable to send value, recipient may have reverted"); - } - - /** - * @dev Performs a Solidity function call using a low level `call`. A - * plain `call` is an unsafe replacement for a function call: use this - * function instead. - * - * If `target` reverts with a revert reason, it is bubbled up by this - * function (like regular Solidity function calls). - * - * Returns the raw returned data. To convert to the expected return value, - * use https://solidity.readthedocs.io/en/latest/units-and-global-variables.html?highlight=abi.decode#abi-encoding-and-decoding-functions[`abi.decode`]. - * - * Requirements: - * - * - `target` must be a contract. - * - calling `target` with `data` must not revert. - * - * _Available since v3.1._ - */ - function functionCall(address target, bytes memory data) internal returns (bytes memory) { - return functionCallWithValue(target, data, 0, "Address: low-level call failed"); - } - - /** - * @dev Same as {xref-Address-functionCall-address-bytes-}[`functionCall`], but with - * `errorMessage` as a fallback revert reason when `target` reverts. - * - * _Available since v3.1._ - */ - function functionCall( - address target, - bytes memory data, - string memory errorMessage - ) internal returns (bytes memory) { - return functionCallWithValue(target, data, 0, errorMessage); - } - - /** - * @dev Same as {xref-Address-functionCall-address-bytes-}[`functionCall`], - * but also transferring `value` wei to `target`. - * - * Requirements: - * - * - the calling contract must have an ETH balance of at least `value`. - * - the called Solidity function must be `payable`. - * - * _Available since v3.1._ - */ - function functionCallWithValue( - address target, - bytes memory data, - uint256 value - ) internal returns (bytes memory) { - return functionCallWithValue(target, data, value, "Address: low-level call with value failed"); - } - - /** - * @dev Same as {xref-Address-functionCallWithValue-address-bytes-uint256-}[`functionCallWithValue`], but - * with `errorMessage` as a fallback revert reason when `target` reverts. - * - * _Available since v3.1._ - */ - function functionCallWithValue( - address target, - bytes memory data, - uint256 value, - string memory errorMessage - ) internal returns (bytes memory) { - require(address(this).balance >= value, "Address: insufficient balance for call"); - (bool success, bytes memory returndata) = target.call{value: value}(data); - return verifyCallResultFromTarget(target, success, returndata, errorMessage); - } - - /** - * @dev Same as {xref-Address-functionCall-address-bytes-}[`functionCall`], - * but performing a static call. - * - * _Available since v3.3._ - */ - function functionStaticCall(address target, bytes memory data) internal view returns (bytes memory) { - return functionStaticCall(target, data, "Address: low-level static call failed"); - } - - /** - * @dev Same as {xref-Address-functionCall-address-bytes-string-}[`functionCall`], - * but performing a static call. - * - * _Available since v3.3._ - */ - function functionStaticCall( - address target, - bytes memory data, - string memory errorMessage - ) internal view returns (bytes memory) { - (bool success, bytes memory returndata) = target.staticcall(data); - return verifyCallResultFromTarget(target, success, returndata, errorMessage); - } - - /** - * @dev Same as {xref-Address-functionCall-address-bytes-}[`functionCall`], - * but performing a delegate call. - * - * _Available since v3.4._ - */ - function functionDelegateCall(address target, bytes memory data) internal returns (bytes memory) { - return functionDelegateCall(target, data, "Address: low-level delegate call failed"); - } - - /** - * @dev Same as {xref-Address-functionCall-address-bytes-string-}[`functionCall`], - * but performing a delegate call. - * - * _Available since v3.4._ - */ - function functionDelegateCall( - address target, - bytes memory data, - string memory errorMessage - ) internal returns (bytes memory) { - (bool success, bytes memory returndata) = target.delegatecall(data); - return verifyCallResultFromTarget(target, success, returndata, errorMessage); - } - - /** - * @dev Tool to verify that a low level call to smart-contract was successful, and revert (either by bubbling - * the revert reason or using the provided one) in case of unsuccessful call or if target was not a contract. - * - * _Available since v4.8._ - */ - function verifyCallResultFromTarget( - address target, - bool success, - bytes memory returndata, - string memory errorMessage - ) internal view returns (bytes memory) { - if (success) { - if (returndata.length == 0) { - // only check isContract if the call was successful and the return data is empty - // otherwise we already know that it was a contract - require(isContract(target), "Address: call to non-contract"); - } - return returndata; - } else { - _revert(returndata, errorMessage); - } - } - - /** - * @dev Tool to verify that a low level call was successful, and revert if it wasn't, either by bubbling the - * revert reason or using the provided one. - * - * _Available since v4.3._ - */ - function verifyCallResult( - bool success, - bytes memory returndata, - string memory errorMessage - ) internal pure returns (bytes memory) { - if (success) { - return returndata; - } else { - _revert(returndata, errorMessage); - } - } - - function _revert(bytes memory returndata, string memory errorMessage) private pure { - // Look for revert reason and bubble it up if present - if (returndata.length > 0) { - // The easiest way to bubble the revert reason is using memory via assembly - /// @solidity memory-safe-assembly - assembly { - let returndata_size := mload(returndata) - revert(add(32, returndata), returndata_size) - } - } else { - revert(errorMessage); - } - } -} - -// OpenZeppelin Contracts (last updated v4.6.0) (token/ERC20/IERC20.sol) - - - -/** - * @dev Interface of the ERC20 standard as defined in the EIP. - */ -interface IERC20 { - /** - * @dev Emitted when `value` tokens are moved from one account (`from`) to - * another (`to`). - * - * Note that `value` may be zero. - */ - event Transfer(address indexed from, address indexed to, uint256 value); - - /** - * @dev Emitted when the allowance of a `spender` for an `owner` is set by - * a call to {approve}. `value` is the new allowance. - */ - event Approval(address indexed owner, address indexed spender, uint256 value); - - /** - * @dev Returns the amount of tokens in existence. - */ - function totalSupply() external view returns (uint256); - - /** - * @dev Returns the amount of tokens owned by `account`. - */ - function balanceOf(address account) external view returns (uint256); - - /** - * @dev Moves `amount` tokens from the caller's account to `to`. - * - * Returns a boolean value indicating whether the operation succeeded. - * - * Emits a {Transfer} event. - */ - function transfer(address to, uint256 amount) external returns (bool); - - /** - * @dev Returns the remaining number of tokens that `spender` will be - * allowed to spend on behalf of `owner` through {transferFrom}. This is - * zero by default. - * - * This value changes when {approve} or {transferFrom} are called. - */ - function allowance(address owner, address spender) external view returns (uint256); - - /** - * @dev Sets `amount` as the allowance of `spender` over the caller's tokens. - * - * Returns a boolean value indicating whether the operation succeeded. - * - * IMPORTANT: Beware that changing an allowance with this method brings the risk - * that someone may use both the old and the new allowance by unfortunate - * transaction ordering. One possible solution to mitigate this race - * condition is to first reduce the spender's allowance to 0 and set the - * desired value afterwards: - * https://github.com/ethereum/EIPs/issues/20#issuecomment-263524729 - * - * Emits an {Approval} event. - */ - function approve(address spender, uint256 amount) external returns (bool); - - /** - * @dev Moves `amount` tokens from `from` to `to` using the - * allowance mechanism. `amount` is then deducted from the caller's - * allowance. - * - * Returns a boolean value indicating whether the operation succeeded. - * - * Emits a {Transfer} event. - */ - function transferFrom( - address from, - address to, - uint256 amount - ) external returns (bool); - - - function mint(address account_, uint256 amount_) external; - - function burn(uint256 amount) external; - -} - - - - - - - - - - - -/** - * @dev Wrappers over Solidity's arithmetic operations with added overflow - * checks. - * - * Arithmetic operations in Solidity wrap on overflow. This can easily result - * in bugs, because programmers usually assume that an overflow raises an - * error, which is the standard behavior in high level programming languages. - * `SafeMath` restores this intuition by reverting the transaction when an - * operation overflows. - * - * Using this library instead of the unchecked operations eliminates an entire - * class of bugs, so it's recommended to use it always. - */ -library SafeMath { - /** - * @dev Returns the addition of two unsigned integers, reverting on - * overflow. - * - * Counterpart to Solidity's `+` operator. - * - * Requirements: - * - * - Addition cannot overflow. - */ - function add(uint256 a, uint256 b) internal pure returns (uint256) { - uint256 c = a + b; - require(c >= a, "SafeMath: addition overflow"); - - return c; - } - - /** - * @dev Returns the subtraction of two unsigned integers, reverting on - * overflow (when the result is negative). - * - * Counterpart to Solidity's `-` operator. - * - * Requirements: - * - * - Subtraction cannot overflow. - */ - function sub(uint256 a, uint256 b) internal pure returns (uint256) { - return sub(a, b, "SafeMath: subtraction overflow"); - } - - /** - * @dev Returns the subtraction of two unsigned integers, reverting with custom message on - * overflow (when the result is negative). - * - * Counterpart to Solidity's `-` operator. - * - * Requirements: - * - * - Subtraction cannot overflow. - */ - function sub( - uint256 a, - uint256 b, - string memory errorMessage - ) internal pure returns (uint256) { - require(b <= a, errorMessage); - uint256 c = a - b; - - return c; - } - - /** - * @dev Returns the multiplication of two unsigned integers, reverting on - * overflow. - * - * Counterpart to Solidity's `*` operator. - * - * Requirements: - * - * - Multiplication cannot overflow. - */ - function mul(uint256 a, uint256 b) internal pure returns (uint256) { - // Gas optimization: this is cheaper than requiring 'a' not being zero, but the - // benefit is lost if 'b' is also tested. - // See: https://github.com/OpenZeppelin/openzeppelin-contracts/pull/522 - if (a == 0) { - return 0; - } - - uint256 c = a * b; - require(c / a == b, "SafeMath: multiplication overflow"); - - return c; - } - - /** - * @dev Returns the integer division of two unsigned integers. Reverts on - * division by zero. The result is rounded towards zero. - * - * Counterpart to Solidity's `/` operator. Note: this function uses a - * `revert` opcode (which leaves remaining gas untouched) while Solidity - * uses an invalid opcode to revert (consuming all remaining gas). - * - * Requirements: - * - * - The divisor cannot be zero. - */ - function div(uint256 a, uint256 b) internal pure returns (uint256) { - return div(a, b, "SafeMath: division by zero"); - } - - /** - * @dev Returns the integer division of two unsigned integers. Reverts with custom message on - * division by zero. The result is rounded towards zero. - * - * Counterpart to Solidity's `/` operator. Note: this function uses a - * `revert` opcode (which leaves remaining gas untouched) while Solidity - * uses an invalid opcode to revert (consuming all remaining gas). - * - * Requirements: - * - * - The divisor cannot be zero. - */ - function div( - uint256 a, - uint256 b, - string memory errorMessage - ) internal pure returns (uint256) { - require(b > 0, errorMessage); - uint256 c = a / b; - // assert(a == b * c + a % b); // There is no case in which this doesn't hold - - return c; - } - - /** - * @dev Returns the remainder of dividing two unsigned integers. (unsigned integer modulo), - * Reverts when dividing by zero. - * - * Counterpart to Solidity's `%` operator. This function uses a `revert` - * opcode (which leaves remaining gas untouched) while Solidity uses an - * invalid opcode to revert (consuming all remaining gas). - * - * Requirements: - * - * - The divisor cannot be zero. - */ - function mod(uint256 a, uint256 b) internal pure returns (uint256) { - return mod(a, b, "SafeMath: modulo by zero"); - } - - /** - * @dev Returns the remainder of dividing two unsigned integers. (unsigned integer modulo), - * Reverts with custom message when dividing by zero. - * - * Counterpart to Solidity's `%` operator. This function uses a `revert` - * opcode (which leaves remaining gas untouched) while Solidity uses an - * invalid opcode to revert (consuming all remaining gas). - * - * Requirements: - * - * - The divisor cannot be zero. - */ - function mod( - uint256 a, - uint256 b, - string memory errorMessage - ) internal pure returns (uint256) { - require(b != 0, errorMessage); - return a % b; - } - - // babylonian method (https://en.wikipedia.org/wiki/Methods_of_computing_square_roots#Babylonian_method) - function sqrrt(uint256 a) internal pure returns (uint256 c) { - if (a > 3) { - c = a; - uint256 b = add(div(a, 2), 1); - while (b < c) { - c = b; - b = div(add(div(a, b), b), 2); - } - } else if (a != 0) { - c = 1; - } - } - - /* - * Expects percentage to be trailed by 00, - */ - function percentageAmount(uint256 total_, uint8 percentage_) internal pure returns (uint256 percentAmount_) { - return div(mul(total_, percentage_), 1000); - } - - /* - * Expects percentage to be trailed by 00, - */ - function substractPercentage(uint256 total_, uint8 percentageToSub_) internal pure returns (uint256 result_) { - return sub(total_, div(mul(total_, percentageToSub_), 1000)); - } - - function percentageOfTotal(uint256 part_, uint256 total_) internal pure returns (uint256 percent_) { - return div(mul(part_, 100), total_); - } - - /** - * Taken from Hypersonic https://github.com/M2629/HyperSonic/blob/main/Math.sol - * @dev Returns the average of two numbers. The result is rounded towards - * zero. - */ - function average(uint256 a, uint256 b) internal pure returns (uint256) { - // (a + b) / 2 can overflow, so we distribute - return (a / 2) + (b / 2) + (((a % 2) + (b % 2)) / 2); - } - - function quadraticPricing(uint256 payment_, uint256 multiplier_) internal pure returns (uint256) { - return sqrrt(mul(multiplier_, payment_)); - } - - function bondingCurve(uint256 supply_, uint256 multiplier_) internal pure returns (uint256) { - return mul(multiplier_, supply_); - } -} - -// OpenZeppelin Contracts (last updated v4.7.0) (token/ERC20/utils/SafeERC20.sol) - - - - - -// OpenZeppelin Contracts v4.4.1 (token/ERC20/extensions/draft-IERC20Permit.sol) - - - -/** - * @dev Interface of the ERC20 Permit extension allowing approvals to be made via signatures, as defined in - * https://eips.ethereum.org/EIPS/eip-2612[EIP-2612]. - * - * Adds the {permit} method, which can be used to change an account's ERC20 allowance (see {IERC20-allowance}) by - * presenting a message signed by the account. By not relying on {IERC20-approve}, the token holder account doesn't - * need to send a transaction, and thus is not required to hold Ether at all. - */ -interface IERC20Permit { - /** - * @dev Sets `value` as the allowance of `spender` over ``owner``'s tokens, - * given ``owner``'s signed approval. - * - * IMPORTANT: The same issues {IERC20-approve} has related to transaction - * ordering also apply here. - * - * Emits an {Approval} event. - * - * Requirements: - * - * - `spender` cannot be the zero address. - * - `deadline` must be a timestamp in the future. - * - `v`, `r` and `s` must be a valid `secp256k1` signature from `owner` - * over the EIP712-formatted function arguments. - * - the signature must use ``owner``'s current nonce (see {nonces}). - * - * For more information on the signature format, see the - * https://eips.ethereum.org/EIPS/eip-2612#specification[relevant EIP - * section]. - */ - function permit( - address owner, - address spender, - uint256 value, - uint256 deadline, - uint8 v, - bytes32 r, - bytes32 s - ) external; - - /** - * @dev Returns the current nonce for `owner`. This value must be - * included whenever a signature is generated for {permit}. - * - * Every successful call to {permit} increases ``owner``'s nonce by one. This - * prevents a signature from being used multiple times. - */ - function nonces(address owner) external view returns (uint256); - - /** - * @dev Returns the domain separator used in the encoding of the signature for {permit}, as defined by {EIP712}. - */ - // solhint-disable-next-line func-name-mixedcase - function DOMAIN_SEPARATOR() external view returns (bytes32); -} - - - -/** - * @title SafeERC20 - * @dev Wrappers around ERC20 operations that throw on failure (when the token - * contract returns false). Tokens that return no value (and instead revert or - * throw on failure) are also supported, non-reverting calls are assumed to be - * successful. - * To use this library you can add a `using SafeERC20 for IERC20;` statement to your contract, - * which allows you to call the safe operations as `token.safeTransfer(...)`, etc. - */ -library SafeERC20 { - using Address for address; - - function safeTransfer( - IERC20 token, - address to, - uint256 value - ) internal { - _callOptionalReturn(token, abi.encodeWithSelector(token.transfer.selector, to, value)); - } - - function safeTransferFrom( - IERC20 token, - address from, - address to, - uint256 value - ) internal { - _callOptionalReturn(token, abi.encodeWithSelector(token.transferFrom.selector, from, to, value)); - } - - /** - * @dev Deprecated. This function has issues similar to the ones found in - * {IERC20-approve}, and its usage is discouraged. - * - * Whenever possible, use {safeIncreaseAllowance} and - * {safeDecreaseAllowance} instead. - */ - function safeApprove( - IERC20 token, - address spender, - uint256 value - ) internal { - // safeApprove should only be called when setting an initial allowance, - // or when resetting it to zero. To increase and decrease it, use - // 'safeIncreaseAllowance' and 'safeDecreaseAllowance' - require( - (value == 0) || (token.allowance(address(this), spender) == 0), - "SafeERC20: approve from non-zero to non-zero allowance" - ); - _callOptionalReturn(token, abi.encodeWithSelector(token.approve.selector, spender, value)); - } - - function safeIncreaseAllowance( - IERC20 token, - address spender, - uint256 value - ) internal { - uint256 newAllowance = token.allowance(address(this), spender) + value; - _callOptionalReturn(token, abi.encodeWithSelector(token.approve.selector, spender, newAllowance)); - } - - function safeDecreaseAllowance( - IERC20 token, - address spender, - uint256 value - ) internal { - unchecked { - uint256 oldAllowance = token.allowance(address(this), spender); - require(oldAllowance >= value, "SafeERC20: decreased allowance below zero"); - uint256 newAllowance = oldAllowance - value; - _callOptionalReturn(token, abi.encodeWithSelector(token.approve.selector, spender, newAllowance)); - } - } - - function safePermit( - IERC20Permit token, - address owner, - address spender, - uint256 value, - uint256 deadline, - uint8 v, - bytes32 r, - bytes32 s - ) internal { - uint256 nonceBefore = token.nonces(owner); - token.permit(owner, spender, value, deadline, v, r, s); - uint256 nonceAfter = token.nonces(owner); - require(nonceAfter == nonceBefore + 1, "SafeERC20: permit did not succeed"); - } - - /** - * @dev Imitates a Solidity high-level call (i.e. a regular function call to a contract), relaxing the requirement - * on the return value: the return value is optional (but if data is returned, it must not be false). - * @param token The token targeted by the call. - * @param data The call data (encoded using abi.encode or one of its variants). - */ - function _callOptionalReturn(IERC20 token, bytes memory data) private { - // We need to perform a low level call here, to bypass Solidity's return data size checking mechanism, since - // we're implementing it ourselves. We use {Address.functionCall} to perform this call, which verifies that - // the target address contains contract code and also asserts for success in the low-level call. - - bytes memory returndata = address(token).functionCall(data, "SafeERC20: low-level call failed"); - if (returndata.length > 0) { - // Return data is optional - require(abi.decode(returndata, (bool)), "SafeERC20: ERC20 operation did not succeed"); - } - } -} - - - - - - - - - - - - - - -/** - * @dev Provides information about the current execution context, including the - * sender of the transaction and its data. While these are generally available - * via msg.sender and msg.data, they should not be accessed in such a direct - * manner, since when dealing with meta-transactions the account sending and - * paying for execution may not be the actual sender (as far as an application - * is concerned). - * - * This contract is only required for intermediate, library-like contracts. - */ -abstract contract Context { - function _msgSender() internal view virtual returns (address) { - return msg.sender; - } - - function _msgData() internal view virtual returns (bytes calldata) { - return msg.data; - } -} - - -/** - * @dev Contract module which provides a basic access control mechanism, where - * there is an account (an owner) that can be granted exclusive access to - * specific functions. - * - * By default, the owner account will be the one that deploys the contract. This - * can later be changed with {transferOwnership}. - * - * This module is used through inheritance. It will make available the modifier - * `onlyOwner`, which can be applied to your functions to restrict their use to - * the owner. - */ -abstract contract Ownable is Context { - address private _owner; - - event OwnershipTransferred(address indexed previousOwner, address indexed newOwner); - - /** - * @dev Initializes the contract setting the deployer as the initial owner. - */ - constructor() { - _transferOwnership(_msgSender()); - } - - /** - * @dev Throws if called by any account other than the owner. - */ - modifier onlyOwner() { - _checkOwner(); - _; - } - - /** - * @dev Returns the address of the current owner. - */ - function owner() public view virtual returns (address) { - return _owner; - } - - /** - * @dev Throws if the sender is not the owner. - */ - function _checkOwner() internal view virtual { - require(owner() == _msgSender(), "Ownable: caller is not the owner"); - } - - /** - * @dev Leaves the contract without owner. It will not be possible to call - * `onlyOwner` functions anymore. Can only be called by the current owner. - * - * NOTE: Renouncing ownership will leave the contract without an owner, - * thereby removing any functionality that is only available to the owner. - */ - function renounceOwnership() public virtual onlyOwner { - _transferOwnership(address(0)); - } - - /** - * @dev Transfers ownership of the contract to a new account (`newOwner`). - * Can only be called by the current owner. - */ - function transferOwnership(address newOwner) public virtual onlyOwner { - require(newOwner != address(0), "Ownable: new owner is the zero address"); - _transferOwnership(newOwner); - } - - /** - * @dev Transfers ownership of the contract to a new account (`newOwner`). - * Internal function without access restriction. - */ - function _transferOwnership(address newOwner) internal virtual { - address oldOwner = _owner; - _owner = newOwner; - emit OwnershipTransferred(oldOwner, newOwner); - } -} - - -contract Operator is Ownable { - address public operator; - uint256 constant baseRate = 10000; - - modifier onlyOperator { - require(msg.sender == owner() || msg.sender == operator, "no permission"); - _; - } - - function setOperator(address operator_) external onlyOwner { - operator = operator_; - } - - - function getCurrTime() external view returns(uint256) { - return block.timestamp; - } - - function getBlockNum() external view returns(uint256) { - return block.number; - } - -} - - - - - -/** - * @dev Library for managing - * https://en.wikipedia.org/wiki/Set_(abstract_data_type)[sets] of primitive - * types. - * - * Sets have the following properties: - * - * - Elements are added, removed, and checked for existence in constant time - * (O(1)). - * - Elements are enumerated in O(n). No guarantees are made on the ordering. - * - * ``` - * contract Example { - * // Add the library methods - * using EnumerableSet for EnumerableSet.AddressSet; - * - * // Declare a set state variable - * EnumerableSet.AddressSet private mySet; - * } - * ``` - * - * As of v3.3.0, sets of type `bytes32` (`Bytes32Set`), `address` (`AddressSet`) - * and `uint256` (`UintSet`) are supported. - * - * [WARNING] - * ==== - * Trying to delete such a structure from storage will likely result in data corruption, rendering the structure unusable. - * See https://github.com/ethereum/solidity/pull/11843[ethereum/solidity#11843] for more info. - * - * In order to clean an EnumerableSet, you can either remove all elements one by one or create a fresh instance using an array of EnumerableSet. - * ==== - */ - -library EnumerableSet { - // To implement this library for multiple types with as little code - // repetition as possible, we write it in terms of a generic Set type with - // bytes32 values. - // The Set implementation uses private functions, and user-facing - // implementations (such as AddressSet) are just wrappers around the - // underlying Set. - // This means that we can only create new EnumerableSets for types that fit - // in bytes32. - - struct Set { - // Storage of set values - bytes32[] _values; - // Position of the value in the `values` array, plus 1 because index 0 - // means a value is not in the set. - mapping(bytes32 => uint256) _indexes; - } - - /** - * @dev Add a value to a set. O(1). - * - * Returns true if the value was added to the set, that is if it was not - * already present. - */ - function _add(Set storage set, bytes32 value) private returns (bool) { - if (!_contains(set, value)) { - set._values.push(value); - // The value is stored at length-1, but we add 1 to all indexes - // and use 0 as a sentinel value - set._indexes[value] = set._values.length; - return true; - } else { - return false; - } - } - - /** - * @dev Removes a value from a set. O(1). - * - * Returns true if the value was removed from the set, that is if it was - * present. - */ - function _remove(Set storage set, bytes32 value) private returns (bool) { - // We read and store the value's index to prevent multiple reads from the same storage slot - uint256 valueIndex = set._indexes[value]; - - if (valueIndex != 0) { - // Equivalent to contains(set, value) - // To delete an element from the _values array in O(1), we swap the element to delete with the last one in - // the array, and then remove the last element (sometimes called as 'swap and pop'). - // This modifies the order of the array, as noted in {at}. - - uint256 toDeleteIndex = valueIndex - 1; - uint256 lastIndex = set._values.length - 1; - - if (lastIndex != toDeleteIndex) { - bytes32 lastValue = set._values[lastIndex]; - - // Move the last value to the index where the value to delete is - set._values[toDeleteIndex] = lastValue; - // Update the index for the moved value - set._indexes[lastValue] = valueIndex; // Replace lastValue's index to valueIndex - } - - // Delete the slot where the moved value was stored - set._values.pop(); - - // Delete the index for the deleted slot - delete set._indexes[value]; - - return true; - } else { - return false; - } - } - - /** - * @dev Returns true if the value is in the set. O(1). - */ - function _contains(Set storage set, bytes32 value) private view returns (bool) { - return set._indexes[value] != 0; - } - - /** - * @dev Returns the number of values on the set. O(1). - */ - function _length(Set storage set) private view returns (uint256) { - return set._values.length; - } - - /** - * @dev Returns the value stored at position `index` in the set. O(1). - * - * Note that there are no guarantees on the ordering of values inside the - * array, and it may change when more values are added or removed. - * - * Requirements: - * - * - `index` must be strictly less than {length}. - */ - function _at(Set storage set, uint256 index) private view returns (bytes32) { - return set._values[index]; - } - - /** - * @dev Return the entire set in an array - * - * WARNING: This operation will copy the entire storage to memory, which can be quite expensive. This is designed - * to mostly be used by view accessors that are queried without any gas fees. Developers should keep in mind that - * this function has an unbounded cost, and using it as part of a state-changing function may render the function - * uncallable if the set grows to a point where copying to memory consumes too much gas to fit in a block. - */ - function _values(Set storage set) private view returns (bytes32[] memory) { - return set._values; - } - - // Bytes32Set - - struct Bytes32Set { - Set _inner; - } - - /** - * @dev Add a value to a set. O(1). - * - * Returns true if the value was added to the set, that is if it was not - * already present. - */ - function add(Bytes32Set storage set, bytes32 value) internal returns (bool) { - return _add(set._inner, value); - } - - /** - * @dev Removes a value from a set. O(1). - * - * Returns true if the value was removed from the set, that is if it was - * present. - */ - function remove(Bytes32Set storage set, bytes32 value) internal returns (bool) { - return _remove(set._inner, value); - } - - /** - * @dev Returns true if the value is in the set. O(1). - */ - function contains(Bytes32Set storage set, bytes32 value) internal view returns (bool) { - return _contains(set._inner, value); - } - - /** - * @dev Returns the number of values in the set. O(1). - */ - function length(Bytes32Set storage set) internal view returns (uint256) { - return _length(set._inner); - } - - /** - * @dev Returns the value stored at position `index` in the set. O(1). - * - * Note that there are no guarantees on the ordering of values inside the - * array, and it may change when more values are added or removed. - * - * Requirements: - * - * - `index` must be strictly less than {length}. - */ - function at(Bytes32Set storage set, uint256 index) internal view returns (bytes32) { - return _at(set._inner, index); - } - - /** - * @dev Return the entire set in an array - * - * WARNING: This operation will copy the entire storage to memory, which can be quite expensive. This is designed - * to mostly be used by view accessors that are queried without any gas fees. Developers should keep in mind that - * this function has an unbounded cost, and using it as part of a state-changing function may render the function - * uncallable if the set grows to a point where copying to memory consumes too much gas to fit in a block. - */ - function values(Bytes32Set storage set) internal view returns (bytes32[] memory) { - return _values(set._inner); - } - - // AddressSet - - struct AddressSet { - Set _inner; - } - - /** - * @dev Add a value to a set. O(1). - * - * Returns true if the value was added to the set, that is if it was not - * already present. - */ - function add(AddressSet storage set, address value) internal returns (bool) { - return _add(set._inner, bytes32(uint256(uint160(value)))); - } - - /** - * @dev Removes a value from a set. O(1). - * - * Returns true if the value was removed from the set, that is if it was - * present. - */ - function remove(AddressSet storage set, address value) internal returns (bool) { - return _remove(set._inner, bytes32(uint256(uint160(value)))); - } - - /** - * @dev Returns true if the value is in the set. O(1). - */ - function contains(AddressSet storage set, address value) internal view returns (bool) { - return _contains(set._inner, bytes32(uint256(uint160(value)))); - } - - /** - * @dev Returns the number of values in the set. O(1). - */ - function length(AddressSet storage set) internal view returns (uint256) { - return _length(set._inner); - } - - /** - * @dev Returns the value stored at position `index` in the set. O(1). - * - * Note that there are no guarantees on the ordering of values inside the - * array, and it may change when more values are added or removed. - * - * Requirements: - * - * - `index` must be strictly less than {length}. - */ - function at(AddressSet storage set, uint256 index) internal view returns (address) { - return address(uint160(uint256(_at(set._inner, index)))); - } - - /** - * @dev Return the entire set in an array - * - * WARNING: This operation will copy the entire storage to memory, which can be quite expensive. This is designed - * to mostly be used by view accessors that are queried without any gas fees. Developers should keep in mind that - * this function has an unbounded cost, and using it as part of a state-changing function may render the function - * uncallable if the set grows to a point where copying to memory consumes too much gas to fit in a block. - */ - function values(AddressSet storage set) internal view returns (address[] memory) { - bytes32[] memory store = _values(set._inner); - address[] memory result; - - /// @solidity memory-safe-assembly - assembly { - result := store - } - - return result; - } - - // UintSet - - struct UintSet { - Set _inner; - } - - /** - * @dev Add a value to a set. O(1). - * - * Returns true if the value was added to the set, that is if it was not - * already present. - */ - function add(UintSet storage set, uint256 value) internal returns (bool) { - return _add(set._inner, bytes32(value)); - } - - /** - * @dev Removes a value from a set. O(1). - * - * Returns true if the value was removed from the set, that is if it was - * present. - */ - function remove(UintSet storage set, uint256 value) internal returns (bool) { - return _remove(set._inner, bytes32(value)); - } - - /** - * @dev Returns true if the value is in the set. O(1). - */ - function contains(UintSet storage set, uint256 value) internal view returns (bool) { - return _contains(set._inner, bytes32(value)); - } - - /** - * @dev Returns the number of values on the set. O(1). - */ - function length(UintSet storage set) internal view returns (uint256) { - return _length(set._inner); - } - - /** - * @dev Returns the value stored at position `index` in the set. O(1). - * - * Note that there are no guarantees on the ordering of values inside the - * array, and it may change when more values are added or removed. - * - * Requirements: - * - * - `index` must be strictly less than {length}. - */ - function at(UintSet storage set, uint256 index) internal view returns (uint256) { - return uint256(_at(set._inner, index)); - } - - /** - * @dev Return the entire set in an array - * - * WARNING: This operation will copy the entire storage to memory, which can be quite expensive. This is designed - * to mostly be used by view accessors that are queried without any gas fees. Developers should keep in mind that - * this function has an unbounded cost, and using it as part of a state-changing function may render the function - * uncallable if the set grows to a point where copying to memory consumes too much gas to fit in a block. - */ - function values(UintSet storage set) internal view returns (uint256[] memory) { - bytes32[] memory store = _values(set._inner); - uint256[] memory result; - - /// @solidity memory-safe-assembly - assembly { - result := store - } - - return result; - } -} - - -contract ActivityPool is Operator { - using SafeMath for uint256; - using SafeERC20 for IERC20; - using EnumerableSet for EnumerableSet.AddressSet; - using EnumerableSet for EnumerableSet.UintSet; - - event AddNewAct(uint256 id); - event Bet(address user, uint256 pID, uint256 bType, uint256 amount, uint256 time); - event SetPrize(uint256 pID, uint256 bType); - event Claim(address user, uint256 pID, uint256 bType, uint256 amount); - event RemovePeriodAct(uint256 pID); - - uint256 public constant muti = 1e18; - uint256 public periodID; - uint256 public betID; - - struct UserInfo { - address user; - uint256 pID; - uint256 amount; - uint256 betTime; - uint256 bType; - uint256 claimAmount; - } - - struct ActInfo { - string name; - string aName; - string bName; - address rewardToken; - uint256 startTime; - uint256 endTime; - uint256 minAmount; - uint256 maxAmount; - uint256 aAmount; - uint256 bAmount; - uint256 winType; - bool isBet; - } - - struct TimeInfo { - uint256 time; - uint256 aAmount; - uint256 bAmount; - } - - struct BestInfo { - address aUser; - address bUser; - uint256 aBet; - uint256 bBet; - } - - mapping(uint256 => BestInfo) bestInfo; - mapping(uint256 => uint256) public timeID; - mapping(uint256 => mapping(uint256 => TimeInfo)) public timeInfo; - mapping(address => mapping(uint256 => uint256)) public userBet; - mapping(uint256 => UserInfo) public betInfo; - mapping(uint256 => uint256) public perAmount; - mapping(uint256 => ActInfo) public actInfo; - mapping(uint256 => mapping(uint256 => string)) public descripName; - - mapping(address => EnumerableSet.UintSet) userPid; - mapping(uint256 => EnumerableSet.AddressSet) aUsers; - mapping(uint256 => EnumerableSet.AddressSet) bUsers; - EnumerableSet.UintSet activePeriod; - EnumerableSet.UintSet removePeriod; - - function addNewAct( - string memory name, - string memory aName, - string memory bName, - address token, - uint256 startTime, - uint256 endTime, - uint256 minAmount, - uint256 maxAmount - ) external onlyOperator { - - checkAdd(msg.sender, startTime, endTime, minAmount, maxAmount); - uint256 id = ++periodID; - actInfo[id].name = name; - actInfo[id].aName = aName; - actInfo[id].bName = bName; - actInfo[id].startTime = startTime; - actInfo[id].endTime = endTime; - actInfo[id].minAmount = minAmount; - actInfo[id].maxAmount = maxAmount; - actInfo[id].rewardToken = token; - descripName[id][1] = aName; - descripName[id][2] = bName; - activePeriod.add(id); - - emit AddNewAct(id); - } - - - function removePeriodAct(uint256 pID) external onlyOperator { - checkRemove(pID); - - activePeriod.remove(pID); - removePeriod.add(pID); - - emit RemovePeriodAct(pID); - } - - - function bet(uint256 pID, uint256 bType, uint256 amount) external payable { - checkBet(msg.sender, pID, bType, amount); - if(actInfo[pID].rewardToken == address(0)) { - require(msg.value == amount, "value err"); - } else { - require(msg.value == 0, "value amount err"); - } - - if(bType == 1) { - if(amount > bestInfo[pID].aBet) { - bestInfo[pID].aUser = msg.sender; - bestInfo[pID].aBet = amount; - } - } else { - if(amount > bestInfo[pID].bBet) { - bestInfo[pID].bUser = msg.sender; - bestInfo[pID].bBet = amount; - } - } - - userPid[msg.sender].add(pID); - uint256 id = ++betID; - userBet[msg.sender][pID] = id; - - if(bType == 1) { - aUsers[pID].add(msg.sender); - actInfo[pID].aAmount = actInfo[pID].aAmount.add(amount); - } else { - bUsers[pID].add(msg.sender); - actInfo[pID].bAmount = actInfo[pID].bAmount.add(amount); - } - - actInfo[pID].isBet = true; - betInfo[id].user = msg.sender; - betInfo[id].pID = pID; - betInfo[id].amount = amount; - betInfo[id].betTime = block.timestamp; - betInfo[id].bType = bType; - - uint256 tID = ++timeID[pID]; - timeInfo[pID][tID].time = block.timestamp; - timeInfo[pID][tID].aAmount = actInfo[pID].aAmount; - timeInfo[pID][tID].bAmount = actInfo[pID].bAmount; - - if(actInfo[pID].rewardToken != address(0)) { - IERC20(actInfo[pID].rewardToken).safeTransferFrom(msg.sender, address(this), amount); - } - emit Bet(msg.sender, pID, bType, amount, betInfo[id].betTime); - } - - function setPrize(uint256 pID, uint256 bType) external onlyOperator { - checkSetPrize(msg.sender, pID, bType); - - if(block.timestamp <= actInfo[pID].startTime) { - actInfo[pID].startTime = block.timestamp; - - } - actInfo[pID].endTime = block.timestamp; - - actInfo[pID].winType = bType; - perAmount[pID] = getPerAmount(pID, bType); - - emit SetPrize(pID, bType); - } - - function recive() public payable {} - - function claim(uint256 pID) external { - uint256 amount = checkClaim(msg.sender, pID); - - uint256 id = userBet[msg.sender][pID]; - betInfo[id].claimAmount = amount; - if(actInfo[pID].rewardToken != address(0)) { - IERC20(actInfo[pID].rewardToken).safeTransfer(msg.sender, amount); - } else { - payable(msg.sender).transfer(amount); - } - - emit Claim(msg.sender, pID, betInfo[id].bType, amount); - } - - function checkClaim(address user, uint256 pID) public view returns(uint256 amount) { - require(userPid[user].contains(pID), "not bet"); - uint256 id = userBet[user][pID]; - require(betInfo[id].user == user, "not user"); - require(actInfo[pID].winType != 0, "not prize"); - require(betInfo[id].claimAmount == 0, "has claim"); - - if(actInfo[pID].winType != 3) { - require(actInfo[pID].winType == betInfo[id].bType, "not right"); - amount = perAmount[pID].mul(betInfo[id].amount).div(muti); - require(amount > 0, "no amount"); - } else { - amount = betInfo[id].amount; - } - - return amount; - } - - function getActualRate( - address user, - uint256 pID, - uint256 bType, - uint256 amount - ) external view returns(uint256, uint256, bool) { - if(bType < 1 || bType > 2 || !activePeriod.contains(pID)) { - return (0, 0, false); - } else if(userBet[user][pID] != 0 || actInfo[pID].winType != 0 || amount == 0) { - (uint256 ra, uint256 rb) = getRate(pID, timeID[pID]); - return (ra, rb, false); - } else { - (uint256 aAmount, uint256 bAmount) = (actInfo[pID].aAmount, actInfo[pID].bAmount); - if(bType == 1) { - aAmount = aAmount.add(amount); - } else { - bAmount = bAmount.add(amount); - } - - uint256 total = aAmount.add(bAmount); - if(bAmount == 0 && aAmount != 0) { - return (muti, 0, true); - } - if(bAmount != 0 && aAmount == 0) { - return (0, muti, true); - } - return (total.mul(muti).div(aAmount), total.mul(muti).div(bAmount), true); - } - } - - function getRate(uint256 pID, uint256 tID) public view returns(uint256, uint256) { - (uint256 aAmount, uint256 bAmount) = (timeInfo[pID][tID].aAmount, timeInfo[pID][tID].bAmount); - uint256 total = aAmount.add(bAmount); - if(total == 0) { - return (0, 0); - } - if(bAmount == 0 && aAmount != 0) { - return (muti, 0); - } - if(bAmount != 0 && aAmount == 0) { - return (0, muti); - } - return (total.mul(muti).div(aAmount), total.mul(muti).div(bAmount)); - } - - function getBestInfo(uint256 pID) - external - view - returns(address aUser, address bUser, uint256 aBet, uint256 bBet, uint256 aReward, uint256 bReward) - { - aUser = bestInfo[pID].aUser; - bUser = bestInfo[pID].bUser; - aBet = bestInfo[pID].aBet; - bBet = bestInfo[pID].bBet; - aReward = getPerAmount(pID, 1).mul(aBet).div(muti); - bReward = getPerAmount(pID, 2).mul(bBet).div(muti); - } - - function getPerAmount(uint256 pID, uint256 bType) public view returns(uint256) { - uint256 total = actInfo[pID].aAmount.add(actInfo[pID].bAmount); - if(total == 0) { - return 0; - } - - if(actInfo[pID].winType == 3) { - return muti; - } - - if(bType == 1) { - if(actInfo[pID].aAmount == 0 || actInfo[pID].winType == 2) { - return 0; - } - return total.mul(muti).div(actInfo[pID].aAmount); - } - - if(bType == 2) { - if(actInfo[pID].bAmount == 0 || actInfo[pID].winType == 1) { - return 0; - } - return total.mul(muti).div(actInfo[pID].bAmount); - } - - return 0; - - } - - function checkSetPrize(address user, uint256 pID, uint256 bType) public view returns(bool) { - require(user == owner() || user == operator, "no permission"); - require(bType > 0 && bType <= 3, "type err"); - require(activePeriod.contains(pID), "not active"); - require(actInfo[pID].winType == 0, "has set"); - - return true; - } - - function checkBet( - address user, - uint256 pID, - uint256 bType, - uint256 amount - ) public view returns(bool) { - require(activePeriod.contains(pID), "not active"); - require(actInfo[pID].startTime <= block.timestamp, "not start"); - require(actInfo[pID].endTime > block.timestamp, "has end"); - require(!userPid[user].contains(pID), "has bet"); - require(bType > 0 && bType < 3, "type err"); - require(amount >= actInfo[pID].minAmount && amount <= actInfo[pID].maxAmount, "amount err"); - if(actInfo[pID].rewardToken != address(0)) { - require(IERC20(actInfo[pID].rewardToken).allowance(user, address(this)) >= amount, "not approve enough"); - require(IERC20(actInfo[pID].rewardToken).balanceOf(user) >= amount, "not enough"); - } else { - require(user.balance >= amount, "main token err"); - } - - return true; - } - - - function checkRemove(uint256 pID) public view returns(bool) { - require(activePeriod.contains(pID), "not in"); - require(!actInfo[pID].isBet, "has bet"); - - return true; - } - - function checkAdd( - address user, - uint256 startTime, - uint256 endTime, - uint256 minAmount, - uint256 maxAmount - ) public view returns(bool) { - require(user == owner() || user == operator, "no permission"); - require(startTime > block.timestamp, "startTime err"); - require(endTime > startTime, "endTime err"); - require(minAmount > 0 && maxAmount > minAmount, "amount err"); - - return true; - } - - function getStatus(uint256 pID) external view returns(uint256) { - if(!removePeriod.contains(pID) && !activePeriod.contains(pID)) { - return 5; - } else if(removePeriod.contains(pID)) { - return 6; - } else if(block.timestamp < actInfo[pID].startTime) { - return 1; - } else if ( - actInfo[pID].startTime <= block.timestamp && - actInfo[pID].endTime > block.timestamp - ) { - return 2; - } else if (actInfo[pID].endTime <= block.timestamp && actInfo[pID].winType == 0){ - return 3; - } else if(actInfo[pID].winType != 0) { - return 4; - } - return 0; - } - - function getUserPidNum(address user) external view returns(uint256) { - return userPid[user].length(); - } - - function getUserPid(address user, uint256 index) external view returns(uint256) { - return userPid[user].at(index); - } - - function getAUsersNum(uint256 pID) external view returns(uint256) { - return aUsers[pID].length(); - } - - function getAUsers(uint256 pID, uint256 index) external view returns(address) { - return aUsers[pID].at(index); - } - - function getBUsersNum(uint256 pID) external view returns(uint256) { - return bUsers[pID].length(); - } - - function getBUsers(uint256 pID, uint256 index) external view returns(address) { - return bUsers[pID].at(index); - } - - function getActivePeriodNum() external view returns(uint256) { - return activePeriod.length(); - } - - function getActivePeriod(uint256 index) external view returns(uint256) { - return activePeriod.at(index); - } - - function getRemovePeriodNum() external view returns(uint256) { - return removePeriod.length(); - } - - function getRemovePeriod(uint256 index) external view returns(uint256) { - return removePeriod.at(index); - } -} \ No newline at end of file diff --git a/app/api/uploads/ActivityPool-1729823724402-583299337.sol b/app/api/uploads/ActivityPool-1729823724402-583299337.sol deleted file mode 100644 index daf3372..0000000 --- a/app/api/uploads/ActivityPool-1729823724402-583299337.sol +++ /dev/null @@ -1,1648 +0,0 @@ -// SPDX-License-Identifier: MIT -// OpenZeppelin Contracts (last updated v4.7.0) (utils/Address.sol) - -pragma solidity ^0.8.1; - -/** - * @dev Collection of functions related to the address type - */ -library Address { - /** - * @dev Returns true if `account` is a contract. - * - * [IMPORTANT] - * ==== - * It is unsafe to assume that an address for which this function returns - * false is an externally-owned account (EOA) and not a contract. - * - * Among others, `isContract` will return false for the following - * types of addresses: - * - * - an externally-owned account - * - a contract in construction - * - an address where a contract will be created - * - an address where a contract lived, but was destroyed - * ==== - * - * [IMPORTANT] - * ==== - * You shouldn't rely on `isContract` to protect against flash loan attacks! - * - * Preventing calls from contracts is highly discouraged. It breaks composability, breaks support for smart wallets - * like Gnosis Safe, and does not provide security since it can be circumvented by calling from a contract - * constructor. - * ==== - */ - function isContract(address account) internal view returns (bool) { - // This method relies on extcodesize/address.code.length, which returns 0 - // for contracts in construction, since the code is only stored at the end - // of the constructor execution. - - return account.code.length > 0; - } - - /** - * @dev Replacement for Solidity's `transfer`: sends `amount` wei to - * `recipient`, forwarding all available gas and reverting on errors. - * - * https://eips.ethereum.org/EIPS/eip-1884[EIP1884] increases the gas cost - * of certain opcodes, possibly making contracts go over the 2300 gas limit - * imposed by `transfer`, making them unable to receive funds via - * `transfer`. {sendValue} removes this limitation. - * - * https://diligence.consensys.net/posts/2019/09/stop-using-soliditys-transfer-now/[Learn more]. - * - * IMPORTANT: because control is transferred to `recipient`, care must be - * taken to not create reentrancy vulnerabilities. Consider using - * {ReentrancyGuard} or the - * https://solidity.readthedocs.io/en/v0.5.11/security-considerations.html#use-the-checks-effects-interactions-pattern[checks-effects-interactions pattern]. - */ - function sendValue(address payable recipient, uint256 amount) internal { - require(address(this).balance >= amount, "Address: insufficient balance"); - - (bool success, ) = recipient.call{value: amount}(""); - require(success, "Address: unable to send value, recipient may have reverted"); - } - - /** - * @dev Performs a Solidity function call using a low level `call`. A - * plain `call` is an unsafe replacement for a function call: use this - * function instead. - * - * If `target` reverts with a revert reason, it is bubbled up by this - * function (like regular Solidity function calls). - * - * Returns the raw returned data. To convert to the expected return value, - * use https://solidity.readthedocs.io/en/latest/units-and-global-variables.html?highlight=abi.decode#abi-encoding-and-decoding-functions[`abi.decode`]. - * - * Requirements: - * - * - `target` must be a contract. - * - calling `target` with `data` must not revert. - * - * _Available since v3.1._ - */ - function functionCall(address target, bytes memory data) internal returns (bytes memory) { - return functionCallWithValue(target, data, 0, "Address: low-level call failed"); - } - - /** - * @dev Same as {xref-Address-functionCall-address-bytes-}[`functionCall`], but with - * `errorMessage` as a fallback revert reason when `target` reverts. - * - * _Available since v3.1._ - */ - function functionCall( - address target, - bytes memory data, - string memory errorMessage - ) internal returns (bytes memory) { - return functionCallWithValue(target, data, 0, errorMessage); - } - - /** - * @dev Same as {xref-Address-functionCall-address-bytes-}[`functionCall`], - * but also transferring `value` wei to `target`. - * - * Requirements: - * - * - the calling contract must have an ETH balance of at least `value`. - * - the called Solidity function must be `payable`. - * - * _Available since v3.1._ - */ - function functionCallWithValue( - address target, - bytes memory data, - uint256 value - ) internal returns (bytes memory) { - return functionCallWithValue(target, data, value, "Address: low-level call with value failed"); - } - - /** - * @dev Same as {xref-Address-functionCallWithValue-address-bytes-uint256-}[`functionCallWithValue`], but - * with `errorMessage` as a fallback revert reason when `target` reverts. - * - * _Available since v3.1._ - */ - function functionCallWithValue( - address target, - bytes memory data, - uint256 value, - string memory errorMessage - ) internal returns (bytes memory) { - require(address(this).balance >= value, "Address: insufficient balance for call"); - (bool success, bytes memory returndata) = target.call{value: value}(data); - return verifyCallResultFromTarget(target, success, returndata, errorMessage); - } - - /** - * @dev Same as {xref-Address-functionCall-address-bytes-}[`functionCall`], - * but performing a static call. - * - * _Available since v3.3._ - */ - function functionStaticCall(address target, bytes memory data) internal view returns (bytes memory) { - return functionStaticCall(target, data, "Address: low-level static call failed"); - } - - /** - * @dev Same as {xref-Address-functionCall-address-bytes-string-}[`functionCall`], - * but performing a static call. - * - * _Available since v3.3._ - */ - function functionStaticCall( - address target, - bytes memory data, - string memory errorMessage - ) internal view returns (bytes memory) { - (bool success, bytes memory returndata) = target.staticcall(data); - return verifyCallResultFromTarget(target, success, returndata, errorMessage); - } - - /** - * @dev Same as {xref-Address-functionCall-address-bytes-}[`functionCall`], - * but performing a delegate call. - * - * _Available since v3.4._ - */ - function functionDelegateCall(address target, bytes memory data) internal returns (bytes memory) { - return functionDelegateCall(target, data, "Address: low-level delegate call failed"); - } - - /** - * @dev Same as {xref-Address-functionCall-address-bytes-string-}[`functionCall`], - * but performing a delegate call. - * - * _Available since v3.4._ - */ - function functionDelegateCall( - address target, - bytes memory data, - string memory errorMessage - ) internal returns (bytes memory) { - (bool success, bytes memory returndata) = target.delegatecall(data); - return verifyCallResultFromTarget(target, success, returndata, errorMessage); - } - - /** - * @dev Tool to verify that a low level call to smart-contract was successful, and revert (either by bubbling - * the revert reason or using the provided one) in case of unsuccessful call or if target was not a contract. - * - * _Available since v4.8._ - */ - function verifyCallResultFromTarget( - address target, - bool success, - bytes memory returndata, - string memory errorMessage - ) internal view returns (bytes memory) { - if (success) { - if (returndata.length == 0) { - // only check isContract if the call was successful and the return data is empty - // otherwise we already know that it was a contract - require(isContract(target), "Address: call to non-contract"); - } - return returndata; - } else { - _revert(returndata, errorMessage); - } - } - - /** - * @dev Tool to verify that a low level call was successful, and revert if it wasn't, either by bubbling the - * revert reason or using the provided one. - * - * _Available since v4.3._ - */ - function verifyCallResult( - bool success, - bytes memory returndata, - string memory errorMessage - ) internal pure returns (bytes memory) { - if (success) { - return returndata; - } else { - _revert(returndata, errorMessage); - } - } - - function _revert(bytes memory returndata, string memory errorMessage) private pure { - // Look for revert reason and bubble it up if present - if (returndata.length > 0) { - // The easiest way to bubble the revert reason is using memory via assembly - /// @solidity memory-safe-assembly - assembly { - let returndata_size := mload(returndata) - revert(add(32, returndata), returndata_size) - } - } else { - revert(errorMessage); - } - } -} - -// OpenZeppelin Contracts (last updated v4.6.0) (token/ERC20/IERC20.sol) - - - -/** - * @dev Interface of the ERC20 standard as defined in the EIP. - */ -interface IERC20 { - /** - * @dev Emitted when `value` tokens are moved from one account (`from`) to - * another (`to`). - * - * Note that `value` may be zero. - */ - event Transfer(address indexed from, address indexed to, uint256 value); - - /** - * @dev Emitted when the allowance of a `spender` for an `owner` is set by - * a call to {approve}. `value` is the new allowance. - */ - event Approval(address indexed owner, address indexed spender, uint256 value); - - /** - * @dev Returns the amount of tokens in existence. - */ - function totalSupply() external view returns (uint256); - - /** - * @dev Returns the amount of tokens owned by `account`. - */ - function balanceOf(address account) external view returns (uint256); - - /** - * @dev Moves `amount` tokens from the caller's account to `to`. - * - * Returns a boolean value indicating whether the operation succeeded. - * - * Emits a {Transfer} event. - */ - function transfer(address to, uint256 amount) external returns (bool); - - /** - * @dev Returns the remaining number of tokens that `spender` will be - * allowed to spend on behalf of `owner` through {transferFrom}. This is - * zero by default. - * - * This value changes when {approve} or {transferFrom} are called. - */ - function allowance(address owner, address spender) external view returns (uint256); - - /** - * @dev Sets `amount` as the allowance of `spender` over the caller's tokens. - * - * Returns a boolean value indicating whether the operation succeeded. - * - * IMPORTANT: Beware that changing an allowance with this method brings the risk - * that someone may use both the old and the new allowance by unfortunate - * transaction ordering. One possible solution to mitigate this race - * condition is to first reduce the spender's allowance to 0 and set the - * desired value afterwards: - * https://github.com/ethereum/EIPs/issues/20#issuecomment-263524729 - * - * Emits an {Approval} event. - */ - function approve(address spender, uint256 amount) external returns (bool); - - /** - * @dev Moves `amount` tokens from `from` to `to` using the - * allowance mechanism. `amount` is then deducted from the caller's - * allowance. - * - * Returns a boolean value indicating whether the operation succeeded. - * - * Emits a {Transfer} event. - */ - function transferFrom( - address from, - address to, - uint256 amount - ) external returns (bool); - - - function mint(address account_, uint256 amount_) external; - - function burn(uint256 amount) external; - -} - - - - - - - - - - - -/** - * @dev Wrappers over Solidity's arithmetic operations with added overflow - * checks. - * - * Arithmetic operations in Solidity wrap on overflow. This can easily result - * in bugs, because programmers usually assume that an overflow raises an - * error, which is the standard behavior in high level programming languages. - * `SafeMath` restores this intuition by reverting the transaction when an - * operation overflows. - * - * Using this library instead of the unchecked operations eliminates an entire - * class of bugs, so it's recommended to use it always. - */ -library SafeMath { - /** - * @dev Returns the addition of two unsigned integers, reverting on - * overflow. - * - * Counterpart to Solidity's `+` operator. - * - * Requirements: - * - * - Addition cannot overflow. - */ - function add(uint256 a, uint256 b) internal pure returns (uint256) { - uint256 c = a + b; - require(c >= a, "SafeMath: addition overflow"); - - return c; - } - - /** - * @dev Returns the subtraction of two unsigned integers, reverting on - * overflow (when the result is negative). - * - * Counterpart to Solidity's `-` operator. - * - * Requirements: - * - * - Subtraction cannot overflow. - */ - function sub(uint256 a, uint256 b) internal pure returns (uint256) { - return sub(a, b, "SafeMath: subtraction overflow"); - } - - /** - * @dev Returns the subtraction of two unsigned integers, reverting with custom message on - * overflow (when the result is negative). - * - * Counterpart to Solidity's `-` operator. - * - * Requirements: - * - * - Subtraction cannot overflow. - */ - function sub( - uint256 a, - uint256 b, - string memory errorMessage - ) internal pure returns (uint256) { - require(b <= a, errorMessage); - uint256 c = a - b; - - return c; - } - - /** - * @dev Returns the multiplication of two unsigned integers, reverting on - * overflow. - * - * Counterpart to Solidity's `*` operator. - * - * Requirements: - * - * - Multiplication cannot overflow. - */ - function mul(uint256 a, uint256 b) internal pure returns (uint256) { - // Gas optimization: this is cheaper than requiring 'a' not being zero, but the - // benefit is lost if 'b' is also tested. - // See: https://github.com/OpenZeppelin/openzeppelin-contracts/pull/522 - if (a == 0) { - return 0; - } - - uint256 c = a * b; - require(c / a == b, "SafeMath: multiplication overflow"); - - return c; - } - - /** - * @dev Returns the integer division of two unsigned integers. Reverts on - * division by zero. The result is rounded towards zero. - * - * Counterpart to Solidity's `/` operator. Note: this function uses a - * `revert` opcode (which leaves remaining gas untouched) while Solidity - * uses an invalid opcode to revert (consuming all remaining gas). - * - * Requirements: - * - * - The divisor cannot be zero. - */ - function div(uint256 a, uint256 b) internal pure returns (uint256) { - return div(a, b, "SafeMath: division by zero"); - } - - /** - * @dev Returns the integer division of two unsigned integers. Reverts with custom message on - * division by zero. The result is rounded towards zero. - * - * Counterpart to Solidity's `/` operator. Note: this function uses a - * `revert` opcode (which leaves remaining gas untouched) while Solidity - * uses an invalid opcode to revert (consuming all remaining gas). - * - * Requirements: - * - * - The divisor cannot be zero. - */ - function div( - uint256 a, - uint256 b, - string memory errorMessage - ) internal pure returns (uint256) { - require(b > 0, errorMessage); - uint256 c = a / b; - // assert(a == b * c + a % b); // There is no case in which this doesn't hold - - return c; - } - - /** - * @dev Returns the remainder of dividing two unsigned integers. (unsigned integer modulo), - * Reverts when dividing by zero. - * - * Counterpart to Solidity's `%` operator. This function uses a `revert` - * opcode (which leaves remaining gas untouched) while Solidity uses an - * invalid opcode to revert (consuming all remaining gas). - * - * Requirements: - * - * - The divisor cannot be zero. - */ - function mod(uint256 a, uint256 b) internal pure returns (uint256) { - return mod(a, b, "SafeMath: modulo by zero"); - } - - /** - * @dev Returns the remainder of dividing two unsigned integers. (unsigned integer modulo), - * Reverts with custom message when dividing by zero. - * - * Counterpart to Solidity's `%` operator. This function uses a `revert` - * opcode (which leaves remaining gas untouched) while Solidity uses an - * invalid opcode to revert (consuming all remaining gas). - * - * Requirements: - * - * - The divisor cannot be zero. - */ - function mod( - uint256 a, - uint256 b, - string memory errorMessage - ) internal pure returns (uint256) { - require(b != 0, errorMessage); - return a % b; - } - - // babylonian method (https://en.wikipedia.org/wiki/Methods_of_computing_square_roots#Babylonian_method) - function sqrrt(uint256 a) internal pure returns (uint256 c) { - if (a > 3) { - c = a; - uint256 b = add(div(a, 2), 1); - while (b < c) { - c = b; - b = div(add(div(a, b), b), 2); - } - } else if (a != 0) { - c = 1; - } - } - - /* - * Expects percentage to be trailed by 00, - */ - function percentageAmount(uint256 total_, uint8 percentage_) internal pure returns (uint256 percentAmount_) { - return div(mul(total_, percentage_), 1000); - } - - /* - * Expects percentage to be trailed by 00, - */ - function substractPercentage(uint256 total_, uint8 percentageToSub_) internal pure returns (uint256 result_) { - return sub(total_, div(mul(total_, percentageToSub_), 1000)); - } - - function percentageOfTotal(uint256 part_, uint256 total_) internal pure returns (uint256 percent_) { - return div(mul(part_, 100), total_); - } - - /** - * Taken from Hypersonic https://github.com/M2629/HyperSonic/blob/main/Math.sol - * @dev Returns the average of two numbers. The result is rounded towards - * zero. - */ - function average(uint256 a, uint256 b) internal pure returns (uint256) { - // (a + b) / 2 can overflow, so we distribute - return (a / 2) + (b / 2) + (((a % 2) + (b % 2)) / 2); - } - - function quadraticPricing(uint256 payment_, uint256 multiplier_) internal pure returns (uint256) { - return sqrrt(mul(multiplier_, payment_)); - } - - function bondingCurve(uint256 supply_, uint256 multiplier_) internal pure returns (uint256) { - return mul(multiplier_, supply_); - } -} - -// OpenZeppelin Contracts (last updated v4.7.0) (token/ERC20/utils/SafeERC20.sol) - - - - - -// OpenZeppelin Contracts v4.4.1 (token/ERC20/extensions/draft-IERC20Permit.sol) - - - -/** - * @dev Interface of the ERC20 Permit extension allowing approvals to be made via signatures, as defined in - * https://eips.ethereum.org/EIPS/eip-2612[EIP-2612]. - * - * Adds the {permit} method, which can be used to change an account's ERC20 allowance (see {IERC20-allowance}) by - * presenting a message signed by the account. By not relying on {IERC20-approve}, the token holder account doesn't - * need to send a transaction, and thus is not required to hold Ether at all. - */ -interface IERC20Permit { - /** - * @dev Sets `value` as the allowance of `spender` over ``owner``'s tokens, - * given ``owner``'s signed approval. - * - * IMPORTANT: The same issues {IERC20-approve} has related to transaction - * ordering also apply here. - * - * Emits an {Approval} event. - * - * Requirements: - * - * - `spender` cannot be the zero address. - * - `deadline` must be a timestamp in the future. - * - `v`, `r` and `s` must be a valid `secp256k1` signature from `owner` - * over the EIP712-formatted function arguments. - * - the signature must use ``owner``'s current nonce (see {nonces}). - * - * For more information on the signature format, see the - * https://eips.ethereum.org/EIPS/eip-2612#specification[relevant EIP - * section]. - */ - function permit( - address owner, - address spender, - uint256 value, - uint256 deadline, - uint8 v, - bytes32 r, - bytes32 s - ) external; - - /** - * @dev Returns the current nonce for `owner`. This value must be - * included whenever a signature is generated for {permit}. - * - * Every successful call to {permit} increases ``owner``'s nonce by one. This - * prevents a signature from being used multiple times. - */ - function nonces(address owner) external view returns (uint256); - - /** - * @dev Returns the domain separator used in the encoding of the signature for {permit}, as defined by {EIP712}. - */ - // solhint-disable-next-line func-name-mixedcase - function DOMAIN_SEPARATOR() external view returns (bytes32); -} - - - -/** - * @title SafeERC20 - * @dev Wrappers around ERC20 operations that throw on failure (when the token - * contract returns false). Tokens that return no value (and instead revert or - * throw on failure) are also supported, non-reverting calls are assumed to be - * successful. - * To use this library you can add a `using SafeERC20 for IERC20;` statement to your contract, - * which allows you to call the safe operations as `token.safeTransfer(...)`, etc. - */ -library SafeERC20 { - using Address for address; - - function safeTransfer( - IERC20 token, - address to, - uint256 value - ) internal { - _callOptionalReturn(token, abi.encodeWithSelector(token.transfer.selector, to, value)); - } - - function safeTransferFrom( - IERC20 token, - address from, - address to, - uint256 value - ) internal { - _callOptionalReturn(token, abi.encodeWithSelector(token.transferFrom.selector, from, to, value)); - } - - /** - * @dev Deprecated. This function has issues similar to the ones found in - * {IERC20-approve}, and its usage is discouraged. - * - * Whenever possible, use {safeIncreaseAllowance} and - * {safeDecreaseAllowance} instead. - */ - function safeApprove( - IERC20 token, - address spender, - uint256 value - ) internal { - // safeApprove should only be called when setting an initial allowance, - // or when resetting it to zero. To increase and decrease it, use - // 'safeIncreaseAllowance' and 'safeDecreaseAllowance' - require( - (value == 0) || (token.allowance(address(this), spender) == 0), - "SafeERC20: approve from non-zero to non-zero allowance" - ); - _callOptionalReturn(token, abi.encodeWithSelector(token.approve.selector, spender, value)); - } - - function safeIncreaseAllowance( - IERC20 token, - address spender, - uint256 value - ) internal { - uint256 newAllowance = token.allowance(address(this), spender) + value; - _callOptionalReturn(token, abi.encodeWithSelector(token.approve.selector, spender, newAllowance)); - } - - function safeDecreaseAllowance( - IERC20 token, - address spender, - uint256 value - ) internal { - unchecked { - uint256 oldAllowance = token.allowance(address(this), spender); - require(oldAllowance >= value, "SafeERC20: decreased allowance below zero"); - uint256 newAllowance = oldAllowance - value; - _callOptionalReturn(token, abi.encodeWithSelector(token.approve.selector, spender, newAllowance)); - } - } - - function safePermit( - IERC20Permit token, - address owner, - address spender, - uint256 value, - uint256 deadline, - uint8 v, - bytes32 r, - bytes32 s - ) internal { - uint256 nonceBefore = token.nonces(owner); - token.permit(owner, spender, value, deadline, v, r, s); - uint256 nonceAfter = token.nonces(owner); - require(nonceAfter == nonceBefore + 1, "SafeERC20: permit did not succeed"); - } - - /** - * @dev Imitates a Solidity high-level call (i.e. a regular function call to a contract), relaxing the requirement - * on the return value: the return value is optional (but if data is returned, it must not be false). - * @param token The token targeted by the call. - * @param data The call data (encoded using abi.encode or one of its variants). - */ - function _callOptionalReturn(IERC20 token, bytes memory data) private { - // We need to perform a low level call here, to bypass Solidity's return data size checking mechanism, since - // we're implementing it ourselves. We use {Address.functionCall} to perform this call, which verifies that - // the target address contains contract code and also asserts for success in the low-level call. - - bytes memory returndata = address(token).functionCall(data, "SafeERC20: low-level call failed"); - if (returndata.length > 0) { - // Return data is optional - require(abi.decode(returndata, (bool)), "SafeERC20: ERC20 operation did not succeed"); - } - } -} - - - - - - - - - - - - - - -/** - * @dev Provides information about the current execution context, including the - * sender of the transaction and its data. While these are generally available - * via msg.sender and msg.data, they should not be accessed in such a direct - * manner, since when dealing with meta-transactions the account sending and - * paying for execution may not be the actual sender (as far as an application - * is concerned). - * - * This contract is only required for intermediate, library-like contracts. - */ -abstract contract Context { - function _msgSender() internal view virtual returns (address) { - return msg.sender; - } - - function _msgData() internal view virtual returns (bytes calldata) { - return msg.data; - } -} - - -/** - * @dev Contract module which provides a basic access control mechanism, where - * there is an account (an owner) that can be granted exclusive access to - * specific functions. - * - * By default, the owner account will be the one that deploys the contract. This - * can later be changed with {transferOwnership}. - * - * This module is used through inheritance. It will make available the modifier - * `onlyOwner`, which can be applied to your functions to restrict their use to - * the owner. - */ -abstract contract Ownable is Context { - address private _owner; - - event OwnershipTransferred(address indexed previousOwner, address indexed newOwner); - - /** - * @dev Initializes the contract setting the deployer as the initial owner. - */ - constructor() { - _transferOwnership(_msgSender()); - } - - /** - * @dev Throws if called by any account other than the owner. - */ - modifier onlyOwner() { - _checkOwner(); - _; - } - - /** - * @dev Returns the address of the current owner. - */ - function owner() public view virtual returns (address) { - return _owner; - } - - /** - * @dev Throws if the sender is not the owner. - */ - function _checkOwner() internal view virtual { - require(owner() == _msgSender(), "Ownable: caller is not the owner"); - } - - /** - * @dev Leaves the contract without owner. It will not be possible to call - * `onlyOwner` functions anymore. Can only be called by the current owner. - * - * NOTE: Renouncing ownership will leave the contract without an owner, - * thereby removing any functionality that is only available to the owner. - */ - function renounceOwnership() public virtual onlyOwner { - _transferOwnership(address(0)); - } - - /** - * @dev Transfers ownership of the contract to a new account (`newOwner`). - * Can only be called by the current owner. - */ - function transferOwnership(address newOwner) public virtual onlyOwner { - require(newOwner != address(0), "Ownable: new owner is the zero address"); - _transferOwnership(newOwner); - } - - /** - * @dev Transfers ownership of the contract to a new account (`newOwner`). - * Internal function without access restriction. - */ - function _transferOwnership(address newOwner) internal virtual { - address oldOwner = _owner; - _owner = newOwner; - emit OwnershipTransferred(oldOwner, newOwner); - } -} - - -contract Operator is Ownable { - address public operator; - uint256 constant baseRate = 10000; - - modifier onlyOperator { - require(msg.sender == owner() || msg.sender == operator, "no permission"); - _; - } - - function setOperator(address operator_) external onlyOwner { - operator = operator_; - } - - - function getCurrTime() external view returns(uint256) { - return block.timestamp; - } - - function getBlockNum() external view returns(uint256) { - return block.number; - } - -} - - - - - -/** - * @dev Library for managing - * https://en.wikipedia.org/wiki/Set_(abstract_data_type)[sets] of primitive - * types. - * - * Sets have the following properties: - * - * - Elements are added, removed, and checked for existence in constant time - * (O(1)). - * - Elements are enumerated in O(n). No guarantees are made on the ordering. - * - * ``` - * contract Example { - * // Add the library methods - * using EnumerableSet for EnumerableSet.AddressSet; - * - * // Declare a set state variable - * EnumerableSet.AddressSet private mySet; - * } - * ``` - * - * As of v3.3.0, sets of type `bytes32` (`Bytes32Set`), `address` (`AddressSet`) - * and `uint256` (`UintSet`) are supported. - * - * [WARNING] - * ==== - * Trying to delete such a structure from storage will likely result in data corruption, rendering the structure unusable. - * See https://github.com/ethereum/solidity/pull/11843[ethereum/solidity#11843] for more info. - * - * In order to clean an EnumerableSet, you can either remove all elements one by one or create a fresh instance using an array of EnumerableSet. - * ==== - */ - -library EnumerableSet { - // To implement this library for multiple types with as little code - // repetition as possible, we write it in terms of a generic Set type with - // bytes32 values. - // The Set implementation uses private functions, and user-facing - // implementations (such as AddressSet) are just wrappers around the - // underlying Set. - // This means that we can only create new EnumerableSets for types that fit - // in bytes32. - - struct Set { - // Storage of set values - bytes32[] _values; - // Position of the value in the `values` array, plus 1 because index 0 - // means a value is not in the set. - mapping(bytes32 => uint256) _indexes; - } - - /** - * @dev Add a value to a set. O(1). - * - * Returns true if the value was added to the set, that is if it was not - * already present. - */ - function _add(Set storage set, bytes32 value) private returns (bool) { - if (!_contains(set, value)) { - set._values.push(value); - // The value is stored at length-1, but we add 1 to all indexes - // and use 0 as a sentinel value - set._indexes[value] = set._values.length; - return true; - } else { - return false; - } - } - - /** - * @dev Removes a value from a set. O(1). - * - * Returns true if the value was removed from the set, that is if it was - * present. - */ - function _remove(Set storage set, bytes32 value) private returns (bool) { - // We read and store the value's index to prevent multiple reads from the same storage slot - uint256 valueIndex = set._indexes[value]; - - if (valueIndex != 0) { - // Equivalent to contains(set, value) - // To delete an element from the _values array in O(1), we swap the element to delete with the last one in - // the array, and then remove the last element (sometimes called as 'swap and pop'). - // This modifies the order of the array, as noted in {at}. - - uint256 toDeleteIndex = valueIndex - 1; - uint256 lastIndex = set._values.length - 1; - - if (lastIndex != toDeleteIndex) { - bytes32 lastValue = set._values[lastIndex]; - - // Move the last value to the index where the value to delete is - set._values[toDeleteIndex] = lastValue; - // Update the index for the moved value - set._indexes[lastValue] = valueIndex; // Replace lastValue's index to valueIndex - } - - // Delete the slot where the moved value was stored - set._values.pop(); - - // Delete the index for the deleted slot - delete set._indexes[value]; - - return true; - } else { - return false; - } - } - - /** - * @dev Returns true if the value is in the set. O(1). - */ - function _contains(Set storage set, bytes32 value) private view returns (bool) { - return set._indexes[value] != 0; - } - - /** - * @dev Returns the number of values on the set. O(1). - */ - function _length(Set storage set) private view returns (uint256) { - return set._values.length; - } - - /** - * @dev Returns the value stored at position `index` in the set. O(1). - * - * Note that there are no guarantees on the ordering of values inside the - * array, and it may change when more values are added or removed. - * - * Requirements: - * - * - `index` must be strictly less than {length}. - */ - function _at(Set storage set, uint256 index) private view returns (bytes32) { - return set._values[index]; - } - - /** - * @dev Return the entire set in an array - * - * WARNING: This operation will copy the entire storage to memory, which can be quite expensive. This is designed - * to mostly be used by view accessors that are queried without any gas fees. Developers should keep in mind that - * this function has an unbounded cost, and using it as part of a state-changing function may render the function - * uncallable if the set grows to a point where copying to memory consumes too much gas to fit in a block. - */ - function _values(Set storage set) private view returns (bytes32[] memory) { - return set._values; - } - - // Bytes32Set - - struct Bytes32Set { - Set _inner; - } - - /** - * @dev Add a value to a set. O(1). - * - * Returns true if the value was added to the set, that is if it was not - * already present. - */ - function add(Bytes32Set storage set, bytes32 value) internal returns (bool) { - return _add(set._inner, value); - } - - /** - * @dev Removes a value from a set. O(1). - * - * Returns true if the value was removed from the set, that is if it was - * present. - */ - function remove(Bytes32Set storage set, bytes32 value) internal returns (bool) { - return _remove(set._inner, value); - } - - /** - * @dev Returns true if the value is in the set. O(1). - */ - function contains(Bytes32Set storage set, bytes32 value) internal view returns (bool) { - return _contains(set._inner, value); - } - - /** - * @dev Returns the number of values in the set. O(1). - */ - function length(Bytes32Set storage set) internal view returns (uint256) { - return _length(set._inner); - } - - /** - * @dev Returns the value stored at position `index` in the set. O(1). - * - * Note that there are no guarantees on the ordering of values inside the - * array, and it may change when more values are added or removed. - * - * Requirements: - * - * - `index` must be strictly less than {length}. - */ - function at(Bytes32Set storage set, uint256 index) internal view returns (bytes32) { - return _at(set._inner, index); - } - - /** - * @dev Return the entire set in an array - * - * WARNING: This operation will copy the entire storage to memory, which can be quite expensive. This is designed - * to mostly be used by view accessors that are queried without any gas fees. Developers should keep in mind that - * this function has an unbounded cost, and using it as part of a state-changing function may render the function - * uncallable if the set grows to a point where copying to memory consumes too much gas to fit in a block. - */ - function values(Bytes32Set storage set) internal view returns (bytes32[] memory) { - return _values(set._inner); - } - - // AddressSet - - struct AddressSet { - Set _inner; - } - - /** - * @dev Add a value to a set. O(1). - * - * Returns true if the value was added to the set, that is if it was not - * already present. - */ - function add(AddressSet storage set, address value) internal returns (bool) { - return _add(set._inner, bytes32(uint256(uint160(value)))); - } - - /** - * @dev Removes a value from a set. O(1). - * - * Returns true if the value was removed from the set, that is if it was - * present. - */ - function remove(AddressSet storage set, address value) internal returns (bool) { - return _remove(set._inner, bytes32(uint256(uint160(value)))); - } - - /** - * @dev Returns true if the value is in the set. O(1). - */ - function contains(AddressSet storage set, address value) internal view returns (bool) { - return _contains(set._inner, bytes32(uint256(uint160(value)))); - } - - /** - * @dev Returns the number of values in the set. O(1). - */ - function length(AddressSet storage set) internal view returns (uint256) { - return _length(set._inner); - } - - /** - * @dev Returns the value stored at position `index` in the set. O(1). - * - * Note that there are no guarantees on the ordering of values inside the - * array, and it may change when more values are added or removed. - * - * Requirements: - * - * - `index` must be strictly less than {length}. - */ - function at(AddressSet storage set, uint256 index) internal view returns (address) { - return address(uint160(uint256(_at(set._inner, index)))); - } - - /** - * @dev Return the entire set in an array - * - * WARNING: This operation will copy the entire storage to memory, which can be quite expensive. This is designed - * to mostly be used by view accessors that are queried without any gas fees. Developers should keep in mind that - * this function has an unbounded cost, and using it as part of a state-changing function may render the function - * uncallable if the set grows to a point where copying to memory consumes too much gas to fit in a block. - */ - function values(AddressSet storage set) internal view returns (address[] memory) { - bytes32[] memory store = _values(set._inner); - address[] memory result; - - /// @solidity memory-safe-assembly - assembly { - result := store - } - - return result; - } - - // UintSet - - struct UintSet { - Set _inner; - } - - /** - * @dev Add a value to a set. O(1). - * - * Returns true if the value was added to the set, that is if it was not - * already present. - */ - function add(UintSet storage set, uint256 value) internal returns (bool) { - return _add(set._inner, bytes32(value)); - } - - /** - * @dev Removes a value from a set. O(1). - * - * Returns true if the value was removed from the set, that is if it was - * present. - */ - function remove(UintSet storage set, uint256 value) internal returns (bool) { - return _remove(set._inner, bytes32(value)); - } - - /** - * @dev Returns true if the value is in the set. O(1). - */ - function contains(UintSet storage set, uint256 value) internal view returns (bool) { - return _contains(set._inner, bytes32(value)); - } - - /** - * @dev Returns the number of values on the set. O(1). - */ - function length(UintSet storage set) internal view returns (uint256) { - return _length(set._inner); - } - - /** - * @dev Returns the value stored at position `index` in the set. O(1). - * - * Note that there are no guarantees on the ordering of values inside the - * array, and it may change when more values are added or removed. - * - * Requirements: - * - * - `index` must be strictly less than {length}. - */ - function at(UintSet storage set, uint256 index) internal view returns (uint256) { - return uint256(_at(set._inner, index)); - } - - /** - * @dev Return the entire set in an array - * - * WARNING: This operation will copy the entire storage to memory, which can be quite expensive. This is designed - * to mostly be used by view accessors that are queried without any gas fees. Developers should keep in mind that - * this function has an unbounded cost, and using it as part of a state-changing function may render the function - * uncallable if the set grows to a point where copying to memory consumes too much gas to fit in a block. - */ - function values(UintSet storage set) internal view returns (uint256[] memory) { - bytes32[] memory store = _values(set._inner); - uint256[] memory result; - - /// @solidity memory-safe-assembly - assembly { - result := store - } - - return result; - } -} - - -contract ActivityPool is Operator { - using SafeMath for uint256; - using SafeERC20 for IERC20; - using EnumerableSet for EnumerableSet.AddressSet; - using EnumerableSet for EnumerableSet.UintSet; - - event AddNewAct(uint256 id); - event Bet(address user, uint256 pID, uint256 bType, uint256 amount, uint256 time); - event SetPrize(uint256 pID, uint256 bType); - event Claim(address user, uint256 pID, uint256 bType, uint256 amount); - event RemovePeriodAct(uint256 pID); - - uint256 public constant muti = 1e18; - uint256 public periodID; - uint256 public betID; - - struct UserInfo { - address user; - uint256 pID; - uint256 amount; - uint256 betTime; - uint256 bType; - uint256 claimAmount; - } - - struct ActInfo { - string name; - string aName; - string bName; - address rewardToken; - uint256 startTime; - uint256 endTime; - uint256 minAmount; - uint256 maxAmount; - uint256 aAmount; - uint256 bAmount; - uint256 winType; - bool isBet; - } - - struct TimeInfo { - uint256 time; - uint256 aAmount; - uint256 bAmount; - } - - struct BestInfo { - address aUser; - address bUser; - uint256 aBet; - uint256 bBet; - } - - mapping(uint256 => BestInfo) bestInfo; - mapping(uint256 => uint256) public timeID; - mapping(uint256 => mapping(uint256 => TimeInfo)) public timeInfo; - mapping(address => mapping(uint256 => uint256)) public userBet; - mapping(uint256 => UserInfo) public betInfo; - mapping(uint256 => uint256) public perAmount; - mapping(uint256 => ActInfo) public actInfo; - mapping(uint256 => mapping(uint256 => string)) public descripName; - - mapping(address => EnumerableSet.UintSet) userPid; - mapping(uint256 => EnumerableSet.AddressSet) aUsers; - mapping(uint256 => EnumerableSet.AddressSet) bUsers; - EnumerableSet.UintSet activePeriod; - EnumerableSet.UintSet removePeriod; - - function addNewAct( - string memory name, - string memory aName, - string memory bName, - address token, - uint256 startTime, - uint256 endTime, - uint256 minAmount, - uint256 maxAmount - ) external onlyOperator { - - checkAdd(msg.sender, startTime, endTime, minAmount, maxAmount); - uint256 id = ++periodID; - actInfo[id].name = name; - actInfo[id].aName = aName; - actInfo[id].bName = bName; - actInfo[id].startTime = startTime; - actInfo[id].endTime = endTime; - actInfo[id].minAmount = minAmount; - actInfo[id].maxAmount = maxAmount; - actInfo[id].rewardToken = token; - descripName[id][1] = aName; - descripName[id][2] = bName; - activePeriod.add(id); - - emit AddNewAct(id); - } - - - function removePeriodAct(uint256 pID) external onlyOperator { - checkRemove(pID); - - activePeriod.remove(pID); - removePeriod.add(pID); - - emit RemovePeriodAct(pID); - } - - - function bet(uint256 pID, uint256 bType, uint256 amount) external payable { - checkBet(msg.sender, pID, bType, amount); - if(actInfo[pID].rewardToken == address(0)) { - require(msg.value == amount, "value err"); - } else { - require(msg.value == 0, "value amount err"); - } - - if(bType == 1) { - if(amount > bestInfo[pID].aBet) { - bestInfo[pID].aUser = msg.sender; - bestInfo[pID].aBet = amount; - } - } else { - if(amount > bestInfo[pID].bBet) { - bestInfo[pID].bUser = msg.sender; - bestInfo[pID].bBet = amount; - } - } - - userPid[msg.sender].add(pID); - uint256 id = ++betID; - userBet[msg.sender][pID] = id; - - if(bType == 1) { - aUsers[pID].add(msg.sender); - actInfo[pID].aAmount = actInfo[pID].aAmount.add(amount); - } else { - bUsers[pID].add(msg.sender); - actInfo[pID].bAmount = actInfo[pID].bAmount.add(amount); - } - - actInfo[pID].isBet = true; - betInfo[id].user = msg.sender; - betInfo[id].pID = pID; - betInfo[id].amount = amount; - betInfo[id].betTime = block.timestamp; - betInfo[id].bType = bType; - - uint256 tID = ++timeID[pID]; - timeInfo[pID][tID].time = block.timestamp; - timeInfo[pID][tID].aAmount = actInfo[pID].aAmount; - timeInfo[pID][tID].bAmount = actInfo[pID].bAmount; - - if(actInfo[pID].rewardToken != address(0)) { - IERC20(actInfo[pID].rewardToken).safeTransferFrom(msg.sender, address(this), amount); - } - emit Bet(msg.sender, pID, bType, amount, betInfo[id].betTime); - } - - function setPrize(uint256 pID, uint256 bType) external onlyOperator { - checkSetPrize(msg.sender, pID, bType); - - if(block.timestamp <= actInfo[pID].startTime) { - actInfo[pID].startTime = block.timestamp; - - } - actInfo[pID].endTime = block.timestamp; - - actInfo[pID].winType = bType; - perAmount[pID] = getPerAmount(pID, bType); - - emit SetPrize(pID, bType); - } - - function recive() public payable {} - - function claim(uint256 pID) external { - uint256 amount = checkClaim(msg.sender, pID); - - uint256 id = userBet[msg.sender][pID]; - betInfo[id].claimAmount = amount; - if(actInfo[pID].rewardToken != address(0)) { - IERC20(actInfo[pID].rewardToken).safeTransfer(msg.sender, amount); - } else { - payable(msg.sender).transfer(amount); - } - - emit Claim(msg.sender, pID, betInfo[id].bType, amount); - } - - function checkClaim(address user, uint256 pID) public view returns(uint256 amount) { - require(userPid[user].contains(pID), "not bet"); - uint256 id = userBet[user][pID]; - require(betInfo[id].user == user, "not user"); - require(actInfo[pID].winType != 0, "not prize"); - require(betInfo[id].claimAmount == 0, "has claim"); - - if(actInfo[pID].winType != 3) { - require(actInfo[pID].winType == betInfo[id].bType, "not right"); - amount = perAmount[pID].mul(betInfo[id].amount).div(muti); - require(amount > 0, "no amount"); - } else { - amount = betInfo[id].amount; - } - - return amount; - } - - function getActualRate( - address user, - uint256 pID, - uint256 bType, - uint256 amount - ) external view returns(uint256, uint256, bool) { - if(bType < 1 || bType > 2 || !activePeriod.contains(pID)) { - return (0, 0, false); - } else if(userBet[user][pID] != 0 || actInfo[pID].winType != 0 || amount == 0) { - (uint256 ra, uint256 rb) = getRate(pID, timeID[pID]); - return (ra, rb, false); - } else { - (uint256 aAmount, uint256 bAmount) = (actInfo[pID].aAmount, actInfo[pID].bAmount); - if(bType == 1) { - aAmount = aAmount.add(amount); - } else { - bAmount = bAmount.add(amount); - } - - uint256 total = aAmount.add(bAmount); - if(bAmount == 0 && aAmount != 0) { - return (muti, 0, true); - } - if(bAmount != 0 && aAmount == 0) { - return (0, muti, true); - } - return (total.mul(muti).div(aAmount), total.mul(muti).div(bAmount), true); - } - } - - function getRate(uint256 pID, uint256 tID) public view returns(uint256, uint256) { - (uint256 aAmount, uint256 bAmount) = (timeInfo[pID][tID].aAmount, timeInfo[pID][tID].bAmount); - uint256 total = aAmount.add(bAmount); - if(total == 0) { - return (0, 0); - } - if(bAmount == 0 && aAmount != 0) { - return (muti, 0); - } - if(bAmount != 0 && aAmount == 0) { - return (0, muti); - } - return (total.mul(muti).div(aAmount), total.mul(muti).div(bAmount)); - } - - function getBestInfo(uint256 pID) - external - view - returns(address aUser, address bUser, uint256 aBet, uint256 bBet, uint256 aReward, uint256 bReward) - { - aUser = bestInfo[pID].aUser; - bUser = bestInfo[pID].bUser; - aBet = bestInfo[pID].aBet; - bBet = bestInfo[pID].bBet; - aReward = getPerAmount(pID, 1).mul(aBet).div(muti); - bReward = getPerAmount(pID, 2).mul(bBet).div(muti); - } - - function getPerAmount(uint256 pID, uint256 bType) public view returns(uint256) { - uint256 total = actInfo[pID].aAmount.add(actInfo[pID].bAmount); - if(total == 0) { - return 0; - } - - if(actInfo[pID].winType == 3) { - return muti; - } - - if(bType == 1) { - if(actInfo[pID].aAmount == 0 || actInfo[pID].winType == 2) { - return 0; - } - return total.mul(muti).div(actInfo[pID].aAmount); - } - - if(bType == 2) { - if(actInfo[pID].bAmount == 0 || actInfo[pID].winType == 1) { - return 0; - } - return total.mul(muti).div(actInfo[pID].bAmount); - } - - return 0; - - } - - function checkSetPrize(address user, uint256 pID, uint256 bType) public view returns(bool) { - require(user == owner() || user == operator, "no permission"); - require(bType > 0 && bType <= 3, "type err"); - require(activePeriod.contains(pID), "not active"); - require(actInfo[pID].winType == 0, "has set"); - - return true; - } - - function checkBet( - address user, - uint256 pID, - uint256 bType, - uint256 amount - ) public view returns(bool) { - require(activePeriod.contains(pID), "not active"); - require(actInfo[pID].startTime <= block.timestamp, "not start"); - require(actInfo[pID].endTime > block.timestamp, "has end"); - require(!userPid[user].contains(pID), "has bet"); - require(bType > 0 && bType < 3, "type err"); - require(amount >= actInfo[pID].minAmount && amount <= actInfo[pID].maxAmount, "amount err"); - if(actInfo[pID].rewardToken != address(0)) { - require(IERC20(actInfo[pID].rewardToken).allowance(user, address(this)) >= amount, "not approve enough"); - require(IERC20(actInfo[pID].rewardToken).balanceOf(user) >= amount, "not enough"); - } else { - require(user.balance >= amount, "main token err"); - } - - return true; - } - - - function checkRemove(uint256 pID) public view returns(bool) { - require(activePeriod.contains(pID), "not in"); - require(!actInfo[pID].isBet, "has bet"); - - return true; - } - - function checkAdd( - address user, - uint256 startTime, - uint256 endTime, - uint256 minAmount, - uint256 maxAmount - ) public view returns(bool) { - require(user == owner() || user == operator, "no permission"); - require(startTime > block.timestamp, "startTime err"); - require(endTime > startTime, "endTime err"); - require(minAmount > 0 && maxAmount > minAmount, "amount err"); - - return true; - } - - function getStatus(uint256 pID) external view returns(uint256) { - if(!removePeriod.contains(pID) && !activePeriod.contains(pID)) { - return 5; - } else if(removePeriod.contains(pID)) { - return 6; - } else if(block.timestamp < actInfo[pID].startTime) { - return 1; - } else if ( - actInfo[pID].startTime <= block.timestamp && - actInfo[pID].endTime > block.timestamp - ) { - return 2; - } else if (actInfo[pID].endTime <= block.timestamp && actInfo[pID].winType == 0){ - return 3; - } else if(actInfo[pID].winType != 0) { - return 4; - } - return 0; - } - - function getUserPidNum(address user) external view returns(uint256) { - return userPid[user].length(); - } - - function getUserPid(address user, uint256 index) external view returns(uint256) { - return userPid[user].at(index); - } - - function getAUsersNum(uint256 pID) external view returns(uint256) { - return aUsers[pID].length(); - } - - function getAUsers(uint256 pID, uint256 index) external view returns(address) { - return aUsers[pID].at(index); - } - - function getBUsersNum(uint256 pID) external view returns(uint256) { - return bUsers[pID].length(); - } - - function getBUsers(uint256 pID, uint256 index) external view returns(address) { - return bUsers[pID].at(index); - } - - function getActivePeriodNum() external view returns(uint256) { - return activePeriod.length(); - } - - function getActivePeriod(uint256 index) external view returns(uint256) { - return activePeriod.at(index); - } - - function getRemovePeriodNum() external view returns(uint256) { - return removePeriod.length(); - } - - function getRemovePeriod(uint256 index) external view returns(uint256) { - return removePeriod.at(index); - } -} \ No newline at end of file diff --git a/app/api/uploads/ActivityPool-1729824294573-151604978.sol b/app/api/uploads/ActivityPool-1729824294573-151604978.sol deleted file mode 100644 index daf3372..0000000 --- a/app/api/uploads/ActivityPool-1729824294573-151604978.sol +++ /dev/null @@ -1,1648 +0,0 @@ -// SPDX-License-Identifier: MIT -// OpenZeppelin Contracts (last updated v4.7.0) (utils/Address.sol) - -pragma solidity ^0.8.1; - -/** - * @dev Collection of functions related to the address type - */ -library Address { - /** - * @dev Returns true if `account` is a contract. - * - * [IMPORTANT] - * ==== - * It is unsafe to assume that an address for which this function returns - * false is an externally-owned account (EOA) and not a contract. - * - * Among others, `isContract` will return false for the following - * types of addresses: - * - * - an externally-owned account - * - a contract in construction - * - an address where a contract will be created - * - an address where a contract lived, but was destroyed - * ==== - * - * [IMPORTANT] - * ==== - * You shouldn't rely on `isContract` to protect against flash loan attacks! - * - * Preventing calls from contracts is highly discouraged. It breaks composability, breaks support for smart wallets - * like Gnosis Safe, and does not provide security since it can be circumvented by calling from a contract - * constructor. - * ==== - */ - function isContract(address account) internal view returns (bool) { - // This method relies on extcodesize/address.code.length, which returns 0 - // for contracts in construction, since the code is only stored at the end - // of the constructor execution. - - return account.code.length > 0; - } - - /** - * @dev Replacement for Solidity's `transfer`: sends `amount` wei to - * `recipient`, forwarding all available gas and reverting on errors. - * - * https://eips.ethereum.org/EIPS/eip-1884[EIP1884] increases the gas cost - * of certain opcodes, possibly making contracts go over the 2300 gas limit - * imposed by `transfer`, making them unable to receive funds via - * `transfer`. {sendValue} removes this limitation. - * - * https://diligence.consensys.net/posts/2019/09/stop-using-soliditys-transfer-now/[Learn more]. - * - * IMPORTANT: because control is transferred to `recipient`, care must be - * taken to not create reentrancy vulnerabilities. Consider using - * {ReentrancyGuard} or the - * https://solidity.readthedocs.io/en/v0.5.11/security-considerations.html#use-the-checks-effects-interactions-pattern[checks-effects-interactions pattern]. - */ - function sendValue(address payable recipient, uint256 amount) internal { - require(address(this).balance >= amount, "Address: insufficient balance"); - - (bool success, ) = recipient.call{value: amount}(""); - require(success, "Address: unable to send value, recipient may have reverted"); - } - - /** - * @dev Performs a Solidity function call using a low level `call`. A - * plain `call` is an unsafe replacement for a function call: use this - * function instead. - * - * If `target` reverts with a revert reason, it is bubbled up by this - * function (like regular Solidity function calls). - * - * Returns the raw returned data. To convert to the expected return value, - * use https://solidity.readthedocs.io/en/latest/units-and-global-variables.html?highlight=abi.decode#abi-encoding-and-decoding-functions[`abi.decode`]. - * - * Requirements: - * - * - `target` must be a contract. - * - calling `target` with `data` must not revert. - * - * _Available since v3.1._ - */ - function functionCall(address target, bytes memory data) internal returns (bytes memory) { - return functionCallWithValue(target, data, 0, "Address: low-level call failed"); - } - - /** - * @dev Same as {xref-Address-functionCall-address-bytes-}[`functionCall`], but with - * `errorMessage` as a fallback revert reason when `target` reverts. - * - * _Available since v3.1._ - */ - function functionCall( - address target, - bytes memory data, - string memory errorMessage - ) internal returns (bytes memory) { - return functionCallWithValue(target, data, 0, errorMessage); - } - - /** - * @dev Same as {xref-Address-functionCall-address-bytes-}[`functionCall`], - * but also transferring `value` wei to `target`. - * - * Requirements: - * - * - the calling contract must have an ETH balance of at least `value`. - * - the called Solidity function must be `payable`. - * - * _Available since v3.1._ - */ - function functionCallWithValue( - address target, - bytes memory data, - uint256 value - ) internal returns (bytes memory) { - return functionCallWithValue(target, data, value, "Address: low-level call with value failed"); - } - - /** - * @dev Same as {xref-Address-functionCallWithValue-address-bytes-uint256-}[`functionCallWithValue`], but - * with `errorMessage` as a fallback revert reason when `target` reverts. - * - * _Available since v3.1._ - */ - function functionCallWithValue( - address target, - bytes memory data, - uint256 value, - string memory errorMessage - ) internal returns (bytes memory) { - require(address(this).balance >= value, "Address: insufficient balance for call"); - (bool success, bytes memory returndata) = target.call{value: value}(data); - return verifyCallResultFromTarget(target, success, returndata, errorMessage); - } - - /** - * @dev Same as {xref-Address-functionCall-address-bytes-}[`functionCall`], - * but performing a static call. - * - * _Available since v3.3._ - */ - function functionStaticCall(address target, bytes memory data) internal view returns (bytes memory) { - return functionStaticCall(target, data, "Address: low-level static call failed"); - } - - /** - * @dev Same as {xref-Address-functionCall-address-bytes-string-}[`functionCall`], - * but performing a static call. - * - * _Available since v3.3._ - */ - function functionStaticCall( - address target, - bytes memory data, - string memory errorMessage - ) internal view returns (bytes memory) { - (bool success, bytes memory returndata) = target.staticcall(data); - return verifyCallResultFromTarget(target, success, returndata, errorMessage); - } - - /** - * @dev Same as {xref-Address-functionCall-address-bytes-}[`functionCall`], - * but performing a delegate call. - * - * _Available since v3.4._ - */ - function functionDelegateCall(address target, bytes memory data) internal returns (bytes memory) { - return functionDelegateCall(target, data, "Address: low-level delegate call failed"); - } - - /** - * @dev Same as {xref-Address-functionCall-address-bytes-string-}[`functionCall`], - * but performing a delegate call. - * - * _Available since v3.4._ - */ - function functionDelegateCall( - address target, - bytes memory data, - string memory errorMessage - ) internal returns (bytes memory) { - (bool success, bytes memory returndata) = target.delegatecall(data); - return verifyCallResultFromTarget(target, success, returndata, errorMessage); - } - - /** - * @dev Tool to verify that a low level call to smart-contract was successful, and revert (either by bubbling - * the revert reason or using the provided one) in case of unsuccessful call or if target was not a contract. - * - * _Available since v4.8._ - */ - function verifyCallResultFromTarget( - address target, - bool success, - bytes memory returndata, - string memory errorMessage - ) internal view returns (bytes memory) { - if (success) { - if (returndata.length == 0) { - // only check isContract if the call was successful and the return data is empty - // otherwise we already know that it was a contract - require(isContract(target), "Address: call to non-contract"); - } - return returndata; - } else { - _revert(returndata, errorMessage); - } - } - - /** - * @dev Tool to verify that a low level call was successful, and revert if it wasn't, either by bubbling the - * revert reason or using the provided one. - * - * _Available since v4.3._ - */ - function verifyCallResult( - bool success, - bytes memory returndata, - string memory errorMessage - ) internal pure returns (bytes memory) { - if (success) { - return returndata; - } else { - _revert(returndata, errorMessage); - } - } - - function _revert(bytes memory returndata, string memory errorMessage) private pure { - // Look for revert reason and bubble it up if present - if (returndata.length > 0) { - // The easiest way to bubble the revert reason is using memory via assembly - /// @solidity memory-safe-assembly - assembly { - let returndata_size := mload(returndata) - revert(add(32, returndata), returndata_size) - } - } else { - revert(errorMessage); - } - } -} - -// OpenZeppelin Contracts (last updated v4.6.0) (token/ERC20/IERC20.sol) - - - -/** - * @dev Interface of the ERC20 standard as defined in the EIP. - */ -interface IERC20 { - /** - * @dev Emitted when `value` tokens are moved from one account (`from`) to - * another (`to`). - * - * Note that `value` may be zero. - */ - event Transfer(address indexed from, address indexed to, uint256 value); - - /** - * @dev Emitted when the allowance of a `spender` for an `owner` is set by - * a call to {approve}. `value` is the new allowance. - */ - event Approval(address indexed owner, address indexed spender, uint256 value); - - /** - * @dev Returns the amount of tokens in existence. - */ - function totalSupply() external view returns (uint256); - - /** - * @dev Returns the amount of tokens owned by `account`. - */ - function balanceOf(address account) external view returns (uint256); - - /** - * @dev Moves `amount` tokens from the caller's account to `to`. - * - * Returns a boolean value indicating whether the operation succeeded. - * - * Emits a {Transfer} event. - */ - function transfer(address to, uint256 amount) external returns (bool); - - /** - * @dev Returns the remaining number of tokens that `spender` will be - * allowed to spend on behalf of `owner` through {transferFrom}. This is - * zero by default. - * - * This value changes when {approve} or {transferFrom} are called. - */ - function allowance(address owner, address spender) external view returns (uint256); - - /** - * @dev Sets `amount` as the allowance of `spender` over the caller's tokens. - * - * Returns a boolean value indicating whether the operation succeeded. - * - * IMPORTANT: Beware that changing an allowance with this method brings the risk - * that someone may use both the old and the new allowance by unfortunate - * transaction ordering. One possible solution to mitigate this race - * condition is to first reduce the spender's allowance to 0 and set the - * desired value afterwards: - * https://github.com/ethereum/EIPs/issues/20#issuecomment-263524729 - * - * Emits an {Approval} event. - */ - function approve(address spender, uint256 amount) external returns (bool); - - /** - * @dev Moves `amount` tokens from `from` to `to` using the - * allowance mechanism. `amount` is then deducted from the caller's - * allowance. - * - * Returns a boolean value indicating whether the operation succeeded. - * - * Emits a {Transfer} event. - */ - function transferFrom( - address from, - address to, - uint256 amount - ) external returns (bool); - - - function mint(address account_, uint256 amount_) external; - - function burn(uint256 amount) external; - -} - - - - - - - - - - - -/** - * @dev Wrappers over Solidity's arithmetic operations with added overflow - * checks. - * - * Arithmetic operations in Solidity wrap on overflow. This can easily result - * in bugs, because programmers usually assume that an overflow raises an - * error, which is the standard behavior in high level programming languages. - * `SafeMath` restores this intuition by reverting the transaction when an - * operation overflows. - * - * Using this library instead of the unchecked operations eliminates an entire - * class of bugs, so it's recommended to use it always. - */ -library SafeMath { - /** - * @dev Returns the addition of two unsigned integers, reverting on - * overflow. - * - * Counterpart to Solidity's `+` operator. - * - * Requirements: - * - * - Addition cannot overflow. - */ - function add(uint256 a, uint256 b) internal pure returns (uint256) { - uint256 c = a + b; - require(c >= a, "SafeMath: addition overflow"); - - return c; - } - - /** - * @dev Returns the subtraction of two unsigned integers, reverting on - * overflow (when the result is negative). - * - * Counterpart to Solidity's `-` operator. - * - * Requirements: - * - * - Subtraction cannot overflow. - */ - function sub(uint256 a, uint256 b) internal pure returns (uint256) { - return sub(a, b, "SafeMath: subtraction overflow"); - } - - /** - * @dev Returns the subtraction of two unsigned integers, reverting with custom message on - * overflow (when the result is negative). - * - * Counterpart to Solidity's `-` operator. - * - * Requirements: - * - * - Subtraction cannot overflow. - */ - function sub( - uint256 a, - uint256 b, - string memory errorMessage - ) internal pure returns (uint256) { - require(b <= a, errorMessage); - uint256 c = a - b; - - return c; - } - - /** - * @dev Returns the multiplication of two unsigned integers, reverting on - * overflow. - * - * Counterpart to Solidity's `*` operator. - * - * Requirements: - * - * - Multiplication cannot overflow. - */ - function mul(uint256 a, uint256 b) internal pure returns (uint256) { - // Gas optimization: this is cheaper than requiring 'a' not being zero, but the - // benefit is lost if 'b' is also tested. - // See: https://github.com/OpenZeppelin/openzeppelin-contracts/pull/522 - if (a == 0) { - return 0; - } - - uint256 c = a * b; - require(c / a == b, "SafeMath: multiplication overflow"); - - return c; - } - - /** - * @dev Returns the integer division of two unsigned integers. Reverts on - * division by zero. The result is rounded towards zero. - * - * Counterpart to Solidity's `/` operator. Note: this function uses a - * `revert` opcode (which leaves remaining gas untouched) while Solidity - * uses an invalid opcode to revert (consuming all remaining gas). - * - * Requirements: - * - * - The divisor cannot be zero. - */ - function div(uint256 a, uint256 b) internal pure returns (uint256) { - return div(a, b, "SafeMath: division by zero"); - } - - /** - * @dev Returns the integer division of two unsigned integers. Reverts with custom message on - * division by zero. The result is rounded towards zero. - * - * Counterpart to Solidity's `/` operator. Note: this function uses a - * `revert` opcode (which leaves remaining gas untouched) while Solidity - * uses an invalid opcode to revert (consuming all remaining gas). - * - * Requirements: - * - * - The divisor cannot be zero. - */ - function div( - uint256 a, - uint256 b, - string memory errorMessage - ) internal pure returns (uint256) { - require(b > 0, errorMessage); - uint256 c = a / b; - // assert(a == b * c + a % b); // There is no case in which this doesn't hold - - return c; - } - - /** - * @dev Returns the remainder of dividing two unsigned integers. (unsigned integer modulo), - * Reverts when dividing by zero. - * - * Counterpart to Solidity's `%` operator. This function uses a `revert` - * opcode (which leaves remaining gas untouched) while Solidity uses an - * invalid opcode to revert (consuming all remaining gas). - * - * Requirements: - * - * - The divisor cannot be zero. - */ - function mod(uint256 a, uint256 b) internal pure returns (uint256) { - return mod(a, b, "SafeMath: modulo by zero"); - } - - /** - * @dev Returns the remainder of dividing two unsigned integers. (unsigned integer modulo), - * Reverts with custom message when dividing by zero. - * - * Counterpart to Solidity's `%` operator. This function uses a `revert` - * opcode (which leaves remaining gas untouched) while Solidity uses an - * invalid opcode to revert (consuming all remaining gas). - * - * Requirements: - * - * - The divisor cannot be zero. - */ - function mod( - uint256 a, - uint256 b, - string memory errorMessage - ) internal pure returns (uint256) { - require(b != 0, errorMessage); - return a % b; - } - - // babylonian method (https://en.wikipedia.org/wiki/Methods_of_computing_square_roots#Babylonian_method) - function sqrrt(uint256 a) internal pure returns (uint256 c) { - if (a > 3) { - c = a; - uint256 b = add(div(a, 2), 1); - while (b < c) { - c = b; - b = div(add(div(a, b), b), 2); - } - } else if (a != 0) { - c = 1; - } - } - - /* - * Expects percentage to be trailed by 00, - */ - function percentageAmount(uint256 total_, uint8 percentage_) internal pure returns (uint256 percentAmount_) { - return div(mul(total_, percentage_), 1000); - } - - /* - * Expects percentage to be trailed by 00, - */ - function substractPercentage(uint256 total_, uint8 percentageToSub_) internal pure returns (uint256 result_) { - return sub(total_, div(mul(total_, percentageToSub_), 1000)); - } - - function percentageOfTotal(uint256 part_, uint256 total_) internal pure returns (uint256 percent_) { - return div(mul(part_, 100), total_); - } - - /** - * Taken from Hypersonic https://github.com/M2629/HyperSonic/blob/main/Math.sol - * @dev Returns the average of two numbers. The result is rounded towards - * zero. - */ - function average(uint256 a, uint256 b) internal pure returns (uint256) { - // (a + b) / 2 can overflow, so we distribute - return (a / 2) + (b / 2) + (((a % 2) + (b % 2)) / 2); - } - - function quadraticPricing(uint256 payment_, uint256 multiplier_) internal pure returns (uint256) { - return sqrrt(mul(multiplier_, payment_)); - } - - function bondingCurve(uint256 supply_, uint256 multiplier_) internal pure returns (uint256) { - return mul(multiplier_, supply_); - } -} - -// OpenZeppelin Contracts (last updated v4.7.0) (token/ERC20/utils/SafeERC20.sol) - - - - - -// OpenZeppelin Contracts v4.4.1 (token/ERC20/extensions/draft-IERC20Permit.sol) - - - -/** - * @dev Interface of the ERC20 Permit extension allowing approvals to be made via signatures, as defined in - * https://eips.ethereum.org/EIPS/eip-2612[EIP-2612]. - * - * Adds the {permit} method, which can be used to change an account's ERC20 allowance (see {IERC20-allowance}) by - * presenting a message signed by the account. By not relying on {IERC20-approve}, the token holder account doesn't - * need to send a transaction, and thus is not required to hold Ether at all. - */ -interface IERC20Permit { - /** - * @dev Sets `value` as the allowance of `spender` over ``owner``'s tokens, - * given ``owner``'s signed approval. - * - * IMPORTANT: The same issues {IERC20-approve} has related to transaction - * ordering also apply here. - * - * Emits an {Approval} event. - * - * Requirements: - * - * - `spender` cannot be the zero address. - * - `deadline` must be a timestamp in the future. - * - `v`, `r` and `s` must be a valid `secp256k1` signature from `owner` - * over the EIP712-formatted function arguments. - * - the signature must use ``owner``'s current nonce (see {nonces}). - * - * For more information on the signature format, see the - * https://eips.ethereum.org/EIPS/eip-2612#specification[relevant EIP - * section]. - */ - function permit( - address owner, - address spender, - uint256 value, - uint256 deadline, - uint8 v, - bytes32 r, - bytes32 s - ) external; - - /** - * @dev Returns the current nonce for `owner`. This value must be - * included whenever a signature is generated for {permit}. - * - * Every successful call to {permit} increases ``owner``'s nonce by one. This - * prevents a signature from being used multiple times. - */ - function nonces(address owner) external view returns (uint256); - - /** - * @dev Returns the domain separator used in the encoding of the signature for {permit}, as defined by {EIP712}. - */ - // solhint-disable-next-line func-name-mixedcase - function DOMAIN_SEPARATOR() external view returns (bytes32); -} - - - -/** - * @title SafeERC20 - * @dev Wrappers around ERC20 operations that throw on failure (when the token - * contract returns false). Tokens that return no value (and instead revert or - * throw on failure) are also supported, non-reverting calls are assumed to be - * successful. - * To use this library you can add a `using SafeERC20 for IERC20;` statement to your contract, - * which allows you to call the safe operations as `token.safeTransfer(...)`, etc. - */ -library SafeERC20 { - using Address for address; - - function safeTransfer( - IERC20 token, - address to, - uint256 value - ) internal { - _callOptionalReturn(token, abi.encodeWithSelector(token.transfer.selector, to, value)); - } - - function safeTransferFrom( - IERC20 token, - address from, - address to, - uint256 value - ) internal { - _callOptionalReturn(token, abi.encodeWithSelector(token.transferFrom.selector, from, to, value)); - } - - /** - * @dev Deprecated. This function has issues similar to the ones found in - * {IERC20-approve}, and its usage is discouraged. - * - * Whenever possible, use {safeIncreaseAllowance} and - * {safeDecreaseAllowance} instead. - */ - function safeApprove( - IERC20 token, - address spender, - uint256 value - ) internal { - // safeApprove should only be called when setting an initial allowance, - // or when resetting it to zero. To increase and decrease it, use - // 'safeIncreaseAllowance' and 'safeDecreaseAllowance' - require( - (value == 0) || (token.allowance(address(this), spender) == 0), - "SafeERC20: approve from non-zero to non-zero allowance" - ); - _callOptionalReturn(token, abi.encodeWithSelector(token.approve.selector, spender, value)); - } - - function safeIncreaseAllowance( - IERC20 token, - address spender, - uint256 value - ) internal { - uint256 newAllowance = token.allowance(address(this), spender) + value; - _callOptionalReturn(token, abi.encodeWithSelector(token.approve.selector, spender, newAllowance)); - } - - function safeDecreaseAllowance( - IERC20 token, - address spender, - uint256 value - ) internal { - unchecked { - uint256 oldAllowance = token.allowance(address(this), spender); - require(oldAllowance >= value, "SafeERC20: decreased allowance below zero"); - uint256 newAllowance = oldAllowance - value; - _callOptionalReturn(token, abi.encodeWithSelector(token.approve.selector, spender, newAllowance)); - } - } - - function safePermit( - IERC20Permit token, - address owner, - address spender, - uint256 value, - uint256 deadline, - uint8 v, - bytes32 r, - bytes32 s - ) internal { - uint256 nonceBefore = token.nonces(owner); - token.permit(owner, spender, value, deadline, v, r, s); - uint256 nonceAfter = token.nonces(owner); - require(nonceAfter == nonceBefore + 1, "SafeERC20: permit did not succeed"); - } - - /** - * @dev Imitates a Solidity high-level call (i.e. a regular function call to a contract), relaxing the requirement - * on the return value: the return value is optional (but if data is returned, it must not be false). - * @param token The token targeted by the call. - * @param data The call data (encoded using abi.encode or one of its variants). - */ - function _callOptionalReturn(IERC20 token, bytes memory data) private { - // We need to perform a low level call here, to bypass Solidity's return data size checking mechanism, since - // we're implementing it ourselves. We use {Address.functionCall} to perform this call, which verifies that - // the target address contains contract code and also asserts for success in the low-level call. - - bytes memory returndata = address(token).functionCall(data, "SafeERC20: low-level call failed"); - if (returndata.length > 0) { - // Return data is optional - require(abi.decode(returndata, (bool)), "SafeERC20: ERC20 operation did not succeed"); - } - } -} - - - - - - - - - - - - - - -/** - * @dev Provides information about the current execution context, including the - * sender of the transaction and its data. While these are generally available - * via msg.sender and msg.data, they should not be accessed in such a direct - * manner, since when dealing with meta-transactions the account sending and - * paying for execution may not be the actual sender (as far as an application - * is concerned). - * - * This contract is only required for intermediate, library-like contracts. - */ -abstract contract Context { - function _msgSender() internal view virtual returns (address) { - return msg.sender; - } - - function _msgData() internal view virtual returns (bytes calldata) { - return msg.data; - } -} - - -/** - * @dev Contract module which provides a basic access control mechanism, where - * there is an account (an owner) that can be granted exclusive access to - * specific functions. - * - * By default, the owner account will be the one that deploys the contract. This - * can later be changed with {transferOwnership}. - * - * This module is used through inheritance. It will make available the modifier - * `onlyOwner`, which can be applied to your functions to restrict their use to - * the owner. - */ -abstract contract Ownable is Context { - address private _owner; - - event OwnershipTransferred(address indexed previousOwner, address indexed newOwner); - - /** - * @dev Initializes the contract setting the deployer as the initial owner. - */ - constructor() { - _transferOwnership(_msgSender()); - } - - /** - * @dev Throws if called by any account other than the owner. - */ - modifier onlyOwner() { - _checkOwner(); - _; - } - - /** - * @dev Returns the address of the current owner. - */ - function owner() public view virtual returns (address) { - return _owner; - } - - /** - * @dev Throws if the sender is not the owner. - */ - function _checkOwner() internal view virtual { - require(owner() == _msgSender(), "Ownable: caller is not the owner"); - } - - /** - * @dev Leaves the contract without owner. It will not be possible to call - * `onlyOwner` functions anymore. Can only be called by the current owner. - * - * NOTE: Renouncing ownership will leave the contract without an owner, - * thereby removing any functionality that is only available to the owner. - */ - function renounceOwnership() public virtual onlyOwner { - _transferOwnership(address(0)); - } - - /** - * @dev Transfers ownership of the contract to a new account (`newOwner`). - * Can only be called by the current owner. - */ - function transferOwnership(address newOwner) public virtual onlyOwner { - require(newOwner != address(0), "Ownable: new owner is the zero address"); - _transferOwnership(newOwner); - } - - /** - * @dev Transfers ownership of the contract to a new account (`newOwner`). - * Internal function without access restriction. - */ - function _transferOwnership(address newOwner) internal virtual { - address oldOwner = _owner; - _owner = newOwner; - emit OwnershipTransferred(oldOwner, newOwner); - } -} - - -contract Operator is Ownable { - address public operator; - uint256 constant baseRate = 10000; - - modifier onlyOperator { - require(msg.sender == owner() || msg.sender == operator, "no permission"); - _; - } - - function setOperator(address operator_) external onlyOwner { - operator = operator_; - } - - - function getCurrTime() external view returns(uint256) { - return block.timestamp; - } - - function getBlockNum() external view returns(uint256) { - return block.number; - } - -} - - - - - -/** - * @dev Library for managing - * https://en.wikipedia.org/wiki/Set_(abstract_data_type)[sets] of primitive - * types. - * - * Sets have the following properties: - * - * - Elements are added, removed, and checked for existence in constant time - * (O(1)). - * - Elements are enumerated in O(n). No guarantees are made on the ordering. - * - * ``` - * contract Example { - * // Add the library methods - * using EnumerableSet for EnumerableSet.AddressSet; - * - * // Declare a set state variable - * EnumerableSet.AddressSet private mySet; - * } - * ``` - * - * As of v3.3.0, sets of type `bytes32` (`Bytes32Set`), `address` (`AddressSet`) - * and `uint256` (`UintSet`) are supported. - * - * [WARNING] - * ==== - * Trying to delete such a structure from storage will likely result in data corruption, rendering the structure unusable. - * See https://github.com/ethereum/solidity/pull/11843[ethereum/solidity#11843] for more info. - * - * In order to clean an EnumerableSet, you can either remove all elements one by one or create a fresh instance using an array of EnumerableSet. - * ==== - */ - -library EnumerableSet { - // To implement this library for multiple types with as little code - // repetition as possible, we write it in terms of a generic Set type with - // bytes32 values. - // The Set implementation uses private functions, and user-facing - // implementations (such as AddressSet) are just wrappers around the - // underlying Set. - // This means that we can only create new EnumerableSets for types that fit - // in bytes32. - - struct Set { - // Storage of set values - bytes32[] _values; - // Position of the value in the `values` array, plus 1 because index 0 - // means a value is not in the set. - mapping(bytes32 => uint256) _indexes; - } - - /** - * @dev Add a value to a set. O(1). - * - * Returns true if the value was added to the set, that is if it was not - * already present. - */ - function _add(Set storage set, bytes32 value) private returns (bool) { - if (!_contains(set, value)) { - set._values.push(value); - // The value is stored at length-1, but we add 1 to all indexes - // and use 0 as a sentinel value - set._indexes[value] = set._values.length; - return true; - } else { - return false; - } - } - - /** - * @dev Removes a value from a set. O(1). - * - * Returns true if the value was removed from the set, that is if it was - * present. - */ - function _remove(Set storage set, bytes32 value) private returns (bool) { - // We read and store the value's index to prevent multiple reads from the same storage slot - uint256 valueIndex = set._indexes[value]; - - if (valueIndex != 0) { - // Equivalent to contains(set, value) - // To delete an element from the _values array in O(1), we swap the element to delete with the last one in - // the array, and then remove the last element (sometimes called as 'swap and pop'). - // This modifies the order of the array, as noted in {at}. - - uint256 toDeleteIndex = valueIndex - 1; - uint256 lastIndex = set._values.length - 1; - - if (lastIndex != toDeleteIndex) { - bytes32 lastValue = set._values[lastIndex]; - - // Move the last value to the index where the value to delete is - set._values[toDeleteIndex] = lastValue; - // Update the index for the moved value - set._indexes[lastValue] = valueIndex; // Replace lastValue's index to valueIndex - } - - // Delete the slot where the moved value was stored - set._values.pop(); - - // Delete the index for the deleted slot - delete set._indexes[value]; - - return true; - } else { - return false; - } - } - - /** - * @dev Returns true if the value is in the set. O(1). - */ - function _contains(Set storage set, bytes32 value) private view returns (bool) { - return set._indexes[value] != 0; - } - - /** - * @dev Returns the number of values on the set. O(1). - */ - function _length(Set storage set) private view returns (uint256) { - return set._values.length; - } - - /** - * @dev Returns the value stored at position `index` in the set. O(1). - * - * Note that there are no guarantees on the ordering of values inside the - * array, and it may change when more values are added or removed. - * - * Requirements: - * - * - `index` must be strictly less than {length}. - */ - function _at(Set storage set, uint256 index) private view returns (bytes32) { - return set._values[index]; - } - - /** - * @dev Return the entire set in an array - * - * WARNING: This operation will copy the entire storage to memory, which can be quite expensive. This is designed - * to mostly be used by view accessors that are queried without any gas fees. Developers should keep in mind that - * this function has an unbounded cost, and using it as part of a state-changing function may render the function - * uncallable if the set grows to a point where copying to memory consumes too much gas to fit in a block. - */ - function _values(Set storage set) private view returns (bytes32[] memory) { - return set._values; - } - - // Bytes32Set - - struct Bytes32Set { - Set _inner; - } - - /** - * @dev Add a value to a set. O(1). - * - * Returns true if the value was added to the set, that is if it was not - * already present. - */ - function add(Bytes32Set storage set, bytes32 value) internal returns (bool) { - return _add(set._inner, value); - } - - /** - * @dev Removes a value from a set. O(1). - * - * Returns true if the value was removed from the set, that is if it was - * present. - */ - function remove(Bytes32Set storage set, bytes32 value) internal returns (bool) { - return _remove(set._inner, value); - } - - /** - * @dev Returns true if the value is in the set. O(1). - */ - function contains(Bytes32Set storage set, bytes32 value) internal view returns (bool) { - return _contains(set._inner, value); - } - - /** - * @dev Returns the number of values in the set. O(1). - */ - function length(Bytes32Set storage set) internal view returns (uint256) { - return _length(set._inner); - } - - /** - * @dev Returns the value stored at position `index` in the set. O(1). - * - * Note that there are no guarantees on the ordering of values inside the - * array, and it may change when more values are added or removed. - * - * Requirements: - * - * - `index` must be strictly less than {length}. - */ - function at(Bytes32Set storage set, uint256 index) internal view returns (bytes32) { - return _at(set._inner, index); - } - - /** - * @dev Return the entire set in an array - * - * WARNING: This operation will copy the entire storage to memory, which can be quite expensive. This is designed - * to mostly be used by view accessors that are queried without any gas fees. Developers should keep in mind that - * this function has an unbounded cost, and using it as part of a state-changing function may render the function - * uncallable if the set grows to a point where copying to memory consumes too much gas to fit in a block. - */ - function values(Bytes32Set storage set) internal view returns (bytes32[] memory) { - return _values(set._inner); - } - - // AddressSet - - struct AddressSet { - Set _inner; - } - - /** - * @dev Add a value to a set. O(1). - * - * Returns true if the value was added to the set, that is if it was not - * already present. - */ - function add(AddressSet storage set, address value) internal returns (bool) { - return _add(set._inner, bytes32(uint256(uint160(value)))); - } - - /** - * @dev Removes a value from a set. O(1). - * - * Returns true if the value was removed from the set, that is if it was - * present. - */ - function remove(AddressSet storage set, address value) internal returns (bool) { - return _remove(set._inner, bytes32(uint256(uint160(value)))); - } - - /** - * @dev Returns true if the value is in the set. O(1). - */ - function contains(AddressSet storage set, address value) internal view returns (bool) { - return _contains(set._inner, bytes32(uint256(uint160(value)))); - } - - /** - * @dev Returns the number of values in the set. O(1). - */ - function length(AddressSet storage set) internal view returns (uint256) { - return _length(set._inner); - } - - /** - * @dev Returns the value stored at position `index` in the set. O(1). - * - * Note that there are no guarantees on the ordering of values inside the - * array, and it may change when more values are added or removed. - * - * Requirements: - * - * - `index` must be strictly less than {length}. - */ - function at(AddressSet storage set, uint256 index) internal view returns (address) { - return address(uint160(uint256(_at(set._inner, index)))); - } - - /** - * @dev Return the entire set in an array - * - * WARNING: This operation will copy the entire storage to memory, which can be quite expensive. This is designed - * to mostly be used by view accessors that are queried without any gas fees. Developers should keep in mind that - * this function has an unbounded cost, and using it as part of a state-changing function may render the function - * uncallable if the set grows to a point where copying to memory consumes too much gas to fit in a block. - */ - function values(AddressSet storage set) internal view returns (address[] memory) { - bytes32[] memory store = _values(set._inner); - address[] memory result; - - /// @solidity memory-safe-assembly - assembly { - result := store - } - - return result; - } - - // UintSet - - struct UintSet { - Set _inner; - } - - /** - * @dev Add a value to a set. O(1). - * - * Returns true if the value was added to the set, that is if it was not - * already present. - */ - function add(UintSet storage set, uint256 value) internal returns (bool) { - return _add(set._inner, bytes32(value)); - } - - /** - * @dev Removes a value from a set. O(1). - * - * Returns true if the value was removed from the set, that is if it was - * present. - */ - function remove(UintSet storage set, uint256 value) internal returns (bool) { - return _remove(set._inner, bytes32(value)); - } - - /** - * @dev Returns true if the value is in the set. O(1). - */ - function contains(UintSet storage set, uint256 value) internal view returns (bool) { - return _contains(set._inner, bytes32(value)); - } - - /** - * @dev Returns the number of values on the set. O(1). - */ - function length(UintSet storage set) internal view returns (uint256) { - return _length(set._inner); - } - - /** - * @dev Returns the value stored at position `index` in the set. O(1). - * - * Note that there are no guarantees on the ordering of values inside the - * array, and it may change when more values are added or removed. - * - * Requirements: - * - * - `index` must be strictly less than {length}. - */ - function at(UintSet storage set, uint256 index) internal view returns (uint256) { - return uint256(_at(set._inner, index)); - } - - /** - * @dev Return the entire set in an array - * - * WARNING: This operation will copy the entire storage to memory, which can be quite expensive. This is designed - * to mostly be used by view accessors that are queried without any gas fees. Developers should keep in mind that - * this function has an unbounded cost, and using it as part of a state-changing function may render the function - * uncallable if the set grows to a point where copying to memory consumes too much gas to fit in a block. - */ - function values(UintSet storage set) internal view returns (uint256[] memory) { - bytes32[] memory store = _values(set._inner); - uint256[] memory result; - - /// @solidity memory-safe-assembly - assembly { - result := store - } - - return result; - } -} - - -contract ActivityPool is Operator { - using SafeMath for uint256; - using SafeERC20 for IERC20; - using EnumerableSet for EnumerableSet.AddressSet; - using EnumerableSet for EnumerableSet.UintSet; - - event AddNewAct(uint256 id); - event Bet(address user, uint256 pID, uint256 bType, uint256 amount, uint256 time); - event SetPrize(uint256 pID, uint256 bType); - event Claim(address user, uint256 pID, uint256 bType, uint256 amount); - event RemovePeriodAct(uint256 pID); - - uint256 public constant muti = 1e18; - uint256 public periodID; - uint256 public betID; - - struct UserInfo { - address user; - uint256 pID; - uint256 amount; - uint256 betTime; - uint256 bType; - uint256 claimAmount; - } - - struct ActInfo { - string name; - string aName; - string bName; - address rewardToken; - uint256 startTime; - uint256 endTime; - uint256 minAmount; - uint256 maxAmount; - uint256 aAmount; - uint256 bAmount; - uint256 winType; - bool isBet; - } - - struct TimeInfo { - uint256 time; - uint256 aAmount; - uint256 bAmount; - } - - struct BestInfo { - address aUser; - address bUser; - uint256 aBet; - uint256 bBet; - } - - mapping(uint256 => BestInfo) bestInfo; - mapping(uint256 => uint256) public timeID; - mapping(uint256 => mapping(uint256 => TimeInfo)) public timeInfo; - mapping(address => mapping(uint256 => uint256)) public userBet; - mapping(uint256 => UserInfo) public betInfo; - mapping(uint256 => uint256) public perAmount; - mapping(uint256 => ActInfo) public actInfo; - mapping(uint256 => mapping(uint256 => string)) public descripName; - - mapping(address => EnumerableSet.UintSet) userPid; - mapping(uint256 => EnumerableSet.AddressSet) aUsers; - mapping(uint256 => EnumerableSet.AddressSet) bUsers; - EnumerableSet.UintSet activePeriod; - EnumerableSet.UintSet removePeriod; - - function addNewAct( - string memory name, - string memory aName, - string memory bName, - address token, - uint256 startTime, - uint256 endTime, - uint256 minAmount, - uint256 maxAmount - ) external onlyOperator { - - checkAdd(msg.sender, startTime, endTime, minAmount, maxAmount); - uint256 id = ++periodID; - actInfo[id].name = name; - actInfo[id].aName = aName; - actInfo[id].bName = bName; - actInfo[id].startTime = startTime; - actInfo[id].endTime = endTime; - actInfo[id].minAmount = minAmount; - actInfo[id].maxAmount = maxAmount; - actInfo[id].rewardToken = token; - descripName[id][1] = aName; - descripName[id][2] = bName; - activePeriod.add(id); - - emit AddNewAct(id); - } - - - function removePeriodAct(uint256 pID) external onlyOperator { - checkRemove(pID); - - activePeriod.remove(pID); - removePeriod.add(pID); - - emit RemovePeriodAct(pID); - } - - - function bet(uint256 pID, uint256 bType, uint256 amount) external payable { - checkBet(msg.sender, pID, bType, amount); - if(actInfo[pID].rewardToken == address(0)) { - require(msg.value == amount, "value err"); - } else { - require(msg.value == 0, "value amount err"); - } - - if(bType == 1) { - if(amount > bestInfo[pID].aBet) { - bestInfo[pID].aUser = msg.sender; - bestInfo[pID].aBet = amount; - } - } else { - if(amount > bestInfo[pID].bBet) { - bestInfo[pID].bUser = msg.sender; - bestInfo[pID].bBet = amount; - } - } - - userPid[msg.sender].add(pID); - uint256 id = ++betID; - userBet[msg.sender][pID] = id; - - if(bType == 1) { - aUsers[pID].add(msg.sender); - actInfo[pID].aAmount = actInfo[pID].aAmount.add(amount); - } else { - bUsers[pID].add(msg.sender); - actInfo[pID].bAmount = actInfo[pID].bAmount.add(amount); - } - - actInfo[pID].isBet = true; - betInfo[id].user = msg.sender; - betInfo[id].pID = pID; - betInfo[id].amount = amount; - betInfo[id].betTime = block.timestamp; - betInfo[id].bType = bType; - - uint256 tID = ++timeID[pID]; - timeInfo[pID][tID].time = block.timestamp; - timeInfo[pID][tID].aAmount = actInfo[pID].aAmount; - timeInfo[pID][tID].bAmount = actInfo[pID].bAmount; - - if(actInfo[pID].rewardToken != address(0)) { - IERC20(actInfo[pID].rewardToken).safeTransferFrom(msg.sender, address(this), amount); - } - emit Bet(msg.sender, pID, bType, amount, betInfo[id].betTime); - } - - function setPrize(uint256 pID, uint256 bType) external onlyOperator { - checkSetPrize(msg.sender, pID, bType); - - if(block.timestamp <= actInfo[pID].startTime) { - actInfo[pID].startTime = block.timestamp; - - } - actInfo[pID].endTime = block.timestamp; - - actInfo[pID].winType = bType; - perAmount[pID] = getPerAmount(pID, bType); - - emit SetPrize(pID, bType); - } - - function recive() public payable {} - - function claim(uint256 pID) external { - uint256 amount = checkClaim(msg.sender, pID); - - uint256 id = userBet[msg.sender][pID]; - betInfo[id].claimAmount = amount; - if(actInfo[pID].rewardToken != address(0)) { - IERC20(actInfo[pID].rewardToken).safeTransfer(msg.sender, amount); - } else { - payable(msg.sender).transfer(amount); - } - - emit Claim(msg.sender, pID, betInfo[id].bType, amount); - } - - function checkClaim(address user, uint256 pID) public view returns(uint256 amount) { - require(userPid[user].contains(pID), "not bet"); - uint256 id = userBet[user][pID]; - require(betInfo[id].user == user, "not user"); - require(actInfo[pID].winType != 0, "not prize"); - require(betInfo[id].claimAmount == 0, "has claim"); - - if(actInfo[pID].winType != 3) { - require(actInfo[pID].winType == betInfo[id].bType, "not right"); - amount = perAmount[pID].mul(betInfo[id].amount).div(muti); - require(amount > 0, "no amount"); - } else { - amount = betInfo[id].amount; - } - - return amount; - } - - function getActualRate( - address user, - uint256 pID, - uint256 bType, - uint256 amount - ) external view returns(uint256, uint256, bool) { - if(bType < 1 || bType > 2 || !activePeriod.contains(pID)) { - return (0, 0, false); - } else if(userBet[user][pID] != 0 || actInfo[pID].winType != 0 || amount == 0) { - (uint256 ra, uint256 rb) = getRate(pID, timeID[pID]); - return (ra, rb, false); - } else { - (uint256 aAmount, uint256 bAmount) = (actInfo[pID].aAmount, actInfo[pID].bAmount); - if(bType == 1) { - aAmount = aAmount.add(amount); - } else { - bAmount = bAmount.add(amount); - } - - uint256 total = aAmount.add(bAmount); - if(bAmount == 0 && aAmount != 0) { - return (muti, 0, true); - } - if(bAmount != 0 && aAmount == 0) { - return (0, muti, true); - } - return (total.mul(muti).div(aAmount), total.mul(muti).div(bAmount), true); - } - } - - function getRate(uint256 pID, uint256 tID) public view returns(uint256, uint256) { - (uint256 aAmount, uint256 bAmount) = (timeInfo[pID][tID].aAmount, timeInfo[pID][tID].bAmount); - uint256 total = aAmount.add(bAmount); - if(total == 0) { - return (0, 0); - } - if(bAmount == 0 && aAmount != 0) { - return (muti, 0); - } - if(bAmount != 0 && aAmount == 0) { - return (0, muti); - } - return (total.mul(muti).div(aAmount), total.mul(muti).div(bAmount)); - } - - function getBestInfo(uint256 pID) - external - view - returns(address aUser, address bUser, uint256 aBet, uint256 bBet, uint256 aReward, uint256 bReward) - { - aUser = bestInfo[pID].aUser; - bUser = bestInfo[pID].bUser; - aBet = bestInfo[pID].aBet; - bBet = bestInfo[pID].bBet; - aReward = getPerAmount(pID, 1).mul(aBet).div(muti); - bReward = getPerAmount(pID, 2).mul(bBet).div(muti); - } - - function getPerAmount(uint256 pID, uint256 bType) public view returns(uint256) { - uint256 total = actInfo[pID].aAmount.add(actInfo[pID].bAmount); - if(total == 0) { - return 0; - } - - if(actInfo[pID].winType == 3) { - return muti; - } - - if(bType == 1) { - if(actInfo[pID].aAmount == 0 || actInfo[pID].winType == 2) { - return 0; - } - return total.mul(muti).div(actInfo[pID].aAmount); - } - - if(bType == 2) { - if(actInfo[pID].bAmount == 0 || actInfo[pID].winType == 1) { - return 0; - } - return total.mul(muti).div(actInfo[pID].bAmount); - } - - return 0; - - } - - function checkSetPrize(address user, uint256 pID, uint256 bType) public view returns(bool) { - require(user == owner() || user == operator, "no permission"); - require(bType > 0 && bType <= 3, "type err"); - require(activePeriod.contains(pID), "not active"); - require(actInfo[pID].winType == 0, "has set"); - - return true; - } - - function checkBet( - address user, - uint256 pID, - uint256 bType, - uint256 amount - ) public view returns(bool) { - require(activePeriod.contains(pID), "not active"); - require(actInfo[pID].startTime <= block.timestamp, "not start"); - require(actInfo[pID].endTime > block.timestamp, "has end"); - require(!userPid[user].contains(pID), "has bet"); - require(bType > 0 && bType < 3, "type err"); - require(amount >= actInfo[pID].minAmount && amount <= actInfo[pID].maxAmount, "amount err"); - if(actInfo[pID].rewardToken != address(0)) { - require(IERC20(actInfo[pID].rewardToken).allowance(user, address(this)) >= amount, "not approve enough"); - require(IERC20(actInfo[pID].rewardToken).balanceOf(user) >= amount, "not enough"); - } else { - require(user.balance >= amount, "main token err"); - } - - return true; - } - - - function checkRemove(uint256 pID) public view returns(bool) { - require(activePeriod.contains(pID), "not in"); - require(!actInfo[pID].isBet, "has bet"); - - return true; - } - - function checkAdd( - address user, - uint256 startTime, - uint256 endTime, - uint256 minAmount, - uint256 maxAmount - ) public view returns(bool) { - require(user == owner() || user == operator, "no permission"); - require(startTime > block.timestamp, "startTime err"); - require(endTime > startTime, "endTime err"); - require(minAmount > 0 && maxAmount > minAmount, "amount err"); - - return true; - } - - function getStatus(uint256 pID) external view returns(uint256) { - if(!removePeriod.contains(pID) && !activePeriod.contains(pID)) { - return 5; - } else if(removePeriod.contains(pID)) { - return 6; - } else if(block.timestamp < actInfo[pID].startTime) { - return 1; - } else if ( - actInfo[pID].startTime <= block.timestamp && - actInfo[pID].endTime > block.timestamp - ) { - return 2; - } else if (actInfo[pID].endTime <= block.timestamp && actInfo[pID].winType == 0){ - return 3; - } else if(actInfo[pID].winType != 0) { - return 4; - } - return 0; - } - - function getUserPidNum(address user) external view returns(uint256) { - return userPid[user].length(); - } - - function getUserPid(address user, uint256 index) external view returns(uint256) { - return userPid[user].at(index); - } - - function getAUsersNum(uint256 pID) external view returns(uint256) { - return aUsers[pID].length(); - } - - function getAUsers(uint256 pID, uint256 index) external view returns(address) { - return aUsers[pID].at(index); - } - - function getBUsersNum(uint256 pID) external view returns(uint256) { - return bUsers[pID].length(); - } - - function getBUsers(uint256 pID, uint256 index) external view returns(address) { - return bUsers[pID].at(index); - } - - function getActivePeriodNum() external view returns(uint256) { - return activePeriod.length(); - } - - function getActivePeriod(uint256 index) external view returns(uint256) { - return activePeriod.at(index); - } - - function getRemovePeriodNum() external view returns(uint256) { - return removePeriod.length(); - } - - function getRemovePeriod(uint256 index) external view returns(uint256) { - return removePeriod.at(index); - } -} \ No newline at end of file diff --git a/app/api/uploads/ActivityPool-1729824388248-854683049.sol b/app/api/uploads/ActivityPool-1729824388248-854683049.sol deleted file mode 100644 index daf3372..0000000 --- a/app/api/uploads/ActivityPool-1729824388248-854683049.sol +++ /dev/null @@ -1,1648 +0,0 @@ -// SPDX-License-Identifier: MIT -// OpenZeppelin Contracts (last updated v4.7.0) (utils/Address.sol) - -pragma solidity ^0.8.1; - -/** - * @dev Collection of functions related to the address type - */ -library Address { - /** - * @dev Returns true if `account` is a contract. - * - * [IMPORTANT] - * ==== - * It is unsafe to assume that an address for which this function returns - * false is an externally-owned account (EOA) and not a contract. - * - * Among others, `isContract` will return false for the following - * types of addresses: - * - * - an externally-owned account - * - a contract in construction - * - an address where a contract will be created - * - an address where a contract lived, but was destroyed - * ==== - * - * [IMPORTANT] - * ==== - * You shouldn't rely on `isContract` to protect against flash loan attacks! - * - * Preventing calls from contracts is highly discouraged. It breaks composability, breaks support for smart wallets - * like Gnosis Safe, and does not provide security since it can be circumvented by calling from a contract - * constructor. - * ==== - */ - function isContract(address account) internal view returns (bool) { - // This method relies on extcodesize/address.code.length, which returns 0 - // for contracts in construction, since the code is only stored at the end - // of the constructor execution. - - return account.code.length > 0; - } - - /** - * @dev Replacement for Solidity's `transfer`: sends `amount` wei to - * `recipient`, forwarding all available gas and reverting on errors. - * - * https://eips.ethereum.org/EIPS/eip-1884[EIP1884] increases the gas cost - * of certain opcodes, possibly making contracts go over the 2300 gas limit - * imposed by `transfer`, making them unable to receive funds via - * `transfer`. {sendValue} removes this limitation. - * - * https://diligence.consensys.net/posts/2019/09/stop-using-soliditys-transfer-now/[Learn more]. - * - * IMPORTANT: because control is transferred to `recipient`, care must be - * taken to not create reentrancy vulnerabilities. Consider using - * {ReentrancyGuard} or the - * https://solidity.readthedocs.io/en/v0.5.11/security-considerations.html#use-the-checks-effects-interactions-pattern[checks-effects-interactions pattern]. - */ - function sendValue(address payable recipient, uint256 amount) internal { - require(address(this).balance >= amount, "Address: insufficient balance"); - - (bool success, ) = recipient.call{value: amount}(""); - require(success, "Address: unable to send value, recipient may have reverted"); - } - - /** - * @dev Performs a Solidity function call using a low level `call`. A - * plain `call` is an unsafe replacement for a function call: use this - * function instead. - * - * If `target` reverts with a revert reason, it is bubbled up by this - * function (like regular Solidity function calls). - * - * Returns the raw returned data. To convert to the expected return value, - * use https://solidity.readthedocs.io/en/latest/units-and-global-variables.html?highlight=abi.decode#abi-encoding-and-decoding-functions[`abi.decode`]. - * - * Requirements: - * - * - `target` must be a contract. - * - calling `target` with `data` must not revert. - * - * _Available since v3.1._ - */ - function functionCall(address target, bytes memory data) internal returns (bytes memory) { - return functionCallWithValue(target, data, 0, "Address: low-level call failed"); - } - - /** - * @dev Same as {xref-Address-functionCall-address-bytes-}[`functionCall`], but with - * `errorMessage` as a fallback revert reason when `target` reverts. - * - * _Available since v3.1._ - */ - function functionCall( - address target, - bytes memory data, - string memory errorMessage - ) internal returns (bytes memory) { - return functionCallWithValue(target, data, 0, errorMessage); - } - - /** - * @dev Same as {xref-Address-functionCall-address-bytes-}[`functionCall`], - * but also transferring `value` wei to `target`. - * - * Requirements: - * - * - the calling contract must have an ETH balance of at least `value`. - * - the called Solidity function must be `payable`. - * - * _Available since v3.1._ - */ - function functionCallWithValue( - address target, - bytes memory data, - uint256 value - ) internal returns (bytes memory) { - return functionCallWithValue(target, data, value, "Address: low-level call with value failed"); - } - - /** - * @dev Same as {xref-Address-functionCallWithValue-address-bytes-uint256-}[`functionCallWithValue`], but - * with `errorMessage` as a fallback revert reason when `target` reverts. - * - * _Available since v3.1._ - */ - function functionCallWithValue( - address target, - bytes memory data, - uint256 value, - string memory errorMessage - ) internal returns (bytes memory) { - require(address(this).balance >= value, "Address: insufficient balance for call"); - (bool success, bytes memory returndata) = target.call{value: value}(data); - return verifyCallResultFromTarget(target, success, returndata, errorMessage); - } - - /** - * @dev Same as {xref-Address-functionCall-address-bytes-}[`functionCall`], - * but performing a static call. - * - * _Available since v3.3._ - */ - function functionStaticCall(address target, bytes memory data) internal view returns (bytes memory) { - return functionStaticCall(target, data, "Address: low-level static call failed"); - } - - /** - * @dev Same as {xref-Address-functionCall-address-bytes-string-}[`functionCall`], - * but performing a static call. - * - * _Available since v3.3._ - */ - function functionStaticCall( - address target, - bytes memory data, - string memory errorMessage - ) internal view returns (bytes memory) { - (bool success, bytes memory returndata) = target.staticcall(data); - return verifyCallResultFromTarget(target, success, returndata, errorMessage); - } - - /** - * @dev Same as {xref-Address-functionCall-address-bytes-}[`functionCall`], - * but performing a delegate call. - * - * _Available since v3.4._ - */ - function functionDelegateCall(address target, bytes memory data) internal returns (bytes memory) { - return functionDelegateCall(target, data, "Address: low-level delegate call failed"); - } - - /** - * @dev Same as {xref-Address-functionCall-address-bytes-string-}[`functionCall`], - * but performing a delegate call. - * - * _Available since v3.4._ - */ - function functionDelegateCall( - address target, - bytes memory data, - string memory errorMessage - ) internal returns (bytes memory) { - (bool success, bytes memory returndata) = target.delegatecall(data); - return verifyCallResultFromTarget(target, success, returndata, errorMessage); - } - - /** - * @dev Tool to verify that a low level call to smart-contract was successful, and revert (either by bubbling - * the revert reason or using the provided one) in case of unsuccessful call or if target was not a contract. - * - * _Available since v4.8._ - */ - function verifyCallResultFromTarget( - address target, - bool success, - bytes memory returndata, - string memory errorMessage - ) internal view returns (bytes memory) { - if (success) { - if (returndata.length == 0) { - // only check isContract if the call was successful and the return data is empty - // otherwise we already know that it was a contract - require(isContract(target), "Address: call to non-contract"); - } - return returndata; - } else { - _revert(returndata, errorMessage); - } - } - - /** - * @dev Tool to verify that a low level call was successful, and revert if it wasn't, either by bubbling the - * revert reason or using the provided one. - * - * _Available since v4.3._ - */ - function verifyCallResult( - bool success, - bytes memory returndata, - string memory errorMessage - ) internal pure returns (bytes memory) { - if (success) { - return returndata; - } else { - _revert(returndata, errorMessage); - } - } - - function _revert(bytes memory returndata, string memory errorMessage) private pure { - // Look for revert reason and bubble it up if present - if (returndata.length > 0) { - // The easiest way to bubble the revert reason is using memory via assembly - /// @solidity memory-safe-assembly - assembly { - let returndata_size := mload(returndata) - revert(add(32, returndata), returndata_size) - } - } else { - revert(errorMessage); - } - } -} - -// OpenZeppelin Contracts (last updated v4.6.0) (token/ERC20/IERC20.sol) - - - -/** - * @dev Interface of the ERC20 standard as defined in the EIP. - */ -interface IERC20 { - /** - * @dev Emitted when `value` tokens are moved from one account (`from`) to - * another (`to`). - * - * Note that `value` may be zero. - */ - event Transfer(address indexed from, address indexed to, uint256 value); - - /** - * @dev Emitted when the allowance of a `spender` for an `owner` is set by - * a call to {approve}. `value` is the new allowance. - */ - event Approval(address indexed owner, address indexed spender, uint256 value); - - /** - * @dev Returns the amount of tokens in existence. - */ - function totalSupply() external view returns (uint256); - - /** - * @dev Returns the amount of tokens owned by `account`. - */ - function balanceOf(address account) external view returns (uint256); - - /** - * @dev Moves `amount` tokens from the caller's account to `to`. - * - * Returns a boolean value indicating whether the operation succeeded. - * - * Emits a {Transfer} event. - */ - function transfer(address to, uint256 amount) external returns (bool); - - /** - * @dev Returns the remaining number of tokens that `spender` will be - * allowed to spend on behalf of `owner` through {transferFrom}. This is - * zero by default. - * - * This value changes when {approve} or {transferFrom} are called. - */ - function allowance(address owner, address spender) external view returns (uint256); - - /** - * @dev Sets `amount` as the allowance of `spender` over the caller's tokens. - * - * Returns a boolean value indicating whether the operation succeeded. - * - * IMPORTANT: Beware that changing an allowance with this method brings the risk - * that someone may use both the old and the new allowance by unfortunate - * transaction ordering. One possible solution to mitigate this race - * condition is to first reduce the spender's allowance to 0 and set the - * desired value afterwards: - * https://github.com/ethereum/EIPs/issues/20#issuecomment-263524729 - * - * Emits an {Approval} event. - */ - function approve(address spender, uint256 amount) external returns (bool); - - /** - * @dev Moves `amount` tokens from `from` to `to` using the - * allowance mechanism. `amount` is then deducted from the caller's - * allowance. - * - * Returns a boolean value indicating whether the operation succeeded. - * - * Emits a {Transfer} event. - */ - function transferFrom( - address from, - address to, - uint256 amount - ) external returns (bool); - - - function mint(address account_, uint256 amount_) external; - - function burn(uint256 amount) external; - -} - - - - - - - - - - - -/** - * @dev Wrappers over Solidity's arithmetic operations with added overflow - * checks. - * - * Arithmetic operations in Solidity wrap on overflow. This can easily result - * in bugs, because programmers usually assume that an overflow raises an - * error, which is the standard behavior in high level programming languages. - * `SafeMath` restores this intuition by reverting the transaction when an - * operation overflows. - * - * Using this library instead of the unchecked operations eliminates an entire - * class of bugs, so it's recommended to use it always. - */ -library SafeMath { - /** - * @dev Returns the addition of two unsigned integers, reverting on - * overflow. - * - * Counterpart to Solidity's `+` operator. - * - * Requirements: - * - * - Addition cannot overflow. - */ - function add(uint256 a, uint256 b) internal pure returns (uint256) { - uint256 c = a + b; - require(c >= a, "SafeMath: addition overflow"); - - return c; - } - - /** - * @dev Returns the subtraction of two unsigned integers, reverting on - * overflow (when the result is negative). - * - * Counterpart to Solidity's `-` operator. - * - * Requirements: - * - * - Subtraction cannot overflow. - */ - function sub(uint256 a, uint256 b) internal pure returns (uint256) { - return sub(a, b, "SafeMath: subtraction overflow"); - } - - /** - * @dev Returns the subtraction of two unsigned integers, reverting with custom message on - * overflow (when the result is negative). - * - * Counterpart to Solidity's `-` operator. - * - * Requirements: - * - * - Subtraction cannot overflow. - */ - function sub( - uint256 a, - uint256 b, - string memory errorMessage - ) internal pure returns (uint256) { - require(b <= a, errorMessage); - uint256 c = a - b; - - return c; - } - - /** - * @dev Returns the multiplication of two unsigned integers, reverting on - * overflow. - * - * Counterpart to Solidity's `*` operator. - * - * Requirements: - * - * - Multiplication cannot overflow. - */ - function mul(uint256 a, uint256 b) internal pure returns (uint256) { - // Gas optimization: this is cheaper than requiring 'a' not being zero, but the - // benefit is lost if 'b' is also tested. - // See: https://github.com/OpenZeppelin/openzeppelin-contracts/pull/522 - if (a == 0) { - return 0; - } - - uint256 c = a * b; - require(c / a == b, "SafeMath: multiplication overflow"); - - return c; - } - - /** - * @dev Returns the integer division of two unsigned integers. Reverts on - * division by zero. The result is rounded towards zero. - * - * Counterpart to Solidity's `/` operator. Note: this function uses a - * `revert` opcode (which leaves remaining gas untouched) while Solidity - * uses an invalid opcode to revert (consuming all remaining gas). - * - * Requirements: - * - * - The divisor cannot be zero. - */ - function div(uint256 a, uint256 b) internal pure returns (uint256) { - return div(a, b, "SafeMath: division by zero"); - } - - /** - * @dev Returns the integer division of two unsigned integers. Reverts with custom message on - * division by zero. The result is rounded towards zero. - * - * Counterpart to Solidity's `/` operator. Note: this function uses a - * `revert` opcode (which leaves remaining gas untouched) while Solidity - * uses an invalid opcode to revert (consuming all remaining gas). - * - * Requirements: - * - * - The divisor cannot be zero. - */ - function div( - uint256 a, - uint256 b, - string memory errorMessage - ) internal pure returns (uint256) { - require(b > 0, errorMessage); - uint256 c = a / b; - // assert(a == b * c + a % b); // There is no case in which this doesn't hold - - return c; - } - - /** - * @dev Returns the remainder of dividing two unsigned integers. (unsigned integer modulo), - * Reverts when dividing by zero. - * - * Counterpart to Solidity's `%` operator. This function uses a `revert` - * opcode (which leaves remaining gas untouched) while Solidity uses an - * invalid opcode to revert (consuming all remaining gas). - * - * Requirements: - * - * - The divisor cannot be zero. - */ - function mod(uint256 a, uint256 b) internal pure returns (uint256) { - return mod(a, b, "SafeMath: modulo by zero"); - } - - /** - * @dev Returns the remainder of dividing two unsigned integers. (unsigned integer modulo), - * Reverts with custom message when dividing by zero. - * - * Counterpart to Solidity's `%` operator. This function uses a `revert` - * opcode (which leaves remaining gas untouched) while Solidity uses an - * invalid opcode to revert (consuming all remaining gas). - * - * Requirements: - * - * - The divisor cannot be zero. - */ - function mod( - uint256 a, - uint256 b, - string memory errorMessage - ) internal pure returns (uint256) { - require(b != 0, errorMessage); - return a % b; - } - - // babylonian method (https://en.wikipedia.org/wiki/Methods_of_computing_square_roots#Babylonian_method) - function sqrrt(uint256 a) internal pure returns (uint256 c) { - if (a > 3) { - c = a; - uint256 b = add(div(a, 2), 1); - while (b < c) { - c = b; - b = div(add(div(a, b), b), 2); - } - } else if (a != 0) { - c = 1; - } - } - - /* - * Expects percentage to be trailed by 00, - */ - function percentageAmount(uint256 total_, uint8 percentage_) internal pure returns (uint256 percentAmount_) { - return div(mul(total_, percentage_), 1000); - } - - /* - * Expects percentage to be trailed by 00, - */ - function substractPercentage(uint256 total_, uint8 percentageToSub_) internal pure returns (uint256 result_) { - return sub(total_, div(mul(total_, percentageToSub_), 1000)); - } - - function percentageOfTotal(uint256 part_, uint256 total_) internal pure returns (uint256 percent_) { - return div(mul(part_, 100), total_); - } - - /** - * Taken from Hypersonic https://github.com/M2629/HyperSonic/blob/main/Math.sol - * @dev Returns the average of two numbers. The result is rounded towards - * zero. - */ - function average(uint256 a, uint256 b) internal pure returns (uint256) { - // (a + b) / 2 can overflow, so we distribute - return (a / 2) + (b / 2) + (((a % 2) + (b % 2)) / 2); - } - - function quadraticPricing(uint256 payment_, uint256 multiplier_) internal pure returns (uint256) { - return sqrrt(mul(multiplier_, payment_)); - } - - function bondingCurve(uint256 supply_, uint256 multiplier_) internal pure returns (uint256) { - return mul(multiplier_, supply_); - } -} - -// OpenZeppelin Contracts (last updated v4.7.0) (token/ERC20/utils/SafeERC20.sol) - - - - - -// OpenZeppelin Contracts v4.4.1 (token/ERC20/extensions/draft-IERC20Permit.sol) - - - -/** - * @dev Interface of the ERC20 Permit extension allowing approvals to be made via signatures, as defined in - * https://eips.ethereum.org/EIPS/eip-2612[EIP-2612]. - * - * Adds the {permit} method, which can be used to change an account's ERC20 allowance (see {IERC20-allowance}) by - * presenting a message signed by the account. By not relying on {IERC20-approve}, the token holder account doesn't - * need to send a transaction, and thus is not required to hold Ether at all. - */ -interface IERC20Permit { - /** - * @dev Sets `value` as the allowance of `spender` over ``owner``'s tokens, - * given ``owner``'s signed approval. - * - * IMPORTANT: The same issues {IERC20-approve} has related to transaction - * ordering also apply here. - * - * Emits an {Approval} event. - * - * Requirements: - * - * - `spender` cannot be the zero address. - * - `deadline` must be a timestamp in the future. - * - `v`, `r` and `s` must be a valid `secp256k1` signature from `owner` - * over the EIP712-formatted function arguments. - * - the signature must use ``owner``'s current nonce (see {nonces}). - * - * For more information on the signature format, see the - * https://eips.ethereum.org/EIPS/eip-2612#specification[relevant EIP - * section]. - */ - function permit( - address owner, - address spender, - uint256 value, - uint256 deadline, - uint8 v, - bytes32 r, - bytes32 s - ) external; - - /** - * @dev Returns the current nonce for `owner`. This value must be - * included whenever a signature is generated for {permit}. - * - * Every successful call to {permit} increases ``owner``'s nonce by one. This - * prevents a signature from being used multiple times. - */ - function nonces(address owner) external view returns (uint256); - - /** - * @dev Returns the domain separator used in the encoding of the signature for {permit}, as defined by {EIP712}. - */ - // solhint-disable-next-line func-name-mixedcase - function DOMAIN_SEPARATOR() external view returns (bytes32); -} - - - -/** - * @title SafeERC20 - * @dev Wrappers around ERC20 operations that throw on failure (when the token - * contract returns false). Tokens that return no value (and instead revert or - * throw on failure) are also supported, non-reverting calls are assumed to be - * successful. - * To use this library you can add a `using SafeERC20 for IERC20;` statement to your contract, - * which allows you to call the safe operations as `token.safeTransfer(...)`, etc. - */ -library SafeERC20 { - using Address for address; - - function safeTransfer( - IERC20 token, - address to, - uint256 value - ) internal { - _callOptionalReturn(token, abi.encodeWithSelector(token.transfer.selector, to, value)); - } - - function safeTransferFrom( - IERC20 token, - address from, - address to, - uint256 value - ) internal { - _callOptionalReturn(token, abi.encodeWithSelector(token.transferFrom.selector, from, to, value)); - } - - /** - * @dev Deprecated. This function has issues similar to the ones found in - * {IERC20-approve}, and its usage is discouraged. - * - * Whenever possible, use {safeIncreaseAllowance} and - * {safeDecreaseAllowance} instead. - */ - function safeApprove( - IERC20 token, - address spender, - uint256 value - ) internal { - // safeApprove should only be called when setting an initial allowance, - // or when resetting it to zero. To increase and decrease it, use - // 'safeIncreaseAllowance' and 'safeDecreaseAllowance' - require( - (value == 0) || (token.allowance(address(this), spender) == 0), - "SafeERC20: approve from non-zero to non-zero allowance" - ); - _callOptionalReturn(token, abi.encodeWithSelector(token.approve.selector, spender, value)); - } - - function safeIncreaseAllowance( - IERC20 token, - address spender, - uint256 value - ) internal { - uint256 newAllowance = token.allowance(address(this), spender) + value; - _callOptionalReturn(token, abi.encodeWithSelector(token.approve.selector, spender, newAllowance)); - } - - function safeDecreaseAllowance( - IERC20 token, - address spender, - uint256 value - ) internal { - unchecked { - uint256 oldAllowance = token.allowance(address(this), spender); - require(oldAllowance >= value, "SafeERC20: decreased allowance below zero"); - uint256 newAllowance = oldAllowance - value; - _callOptionalReturn(token, abi.encodeWithSelector(token.approve.selector, spender, newAllowance)); - } - } - - function safePermit( - IERC20Permit token, - address owner, - address spender, - uint256 value, - uint256 deadline, - uint8 v, - bytes32 r, - bytes32 s - ) internal { - uint256 nonceBefore = token.nonces(owner); - token.permit(owner, spender, value, deadline, v, r, s); - uint256 nonceAfter = token.nonces(owner); - require(nonceAfter == nonceBefore + 1, "SafeERC20: permit did not succeed"); - } - - /** - * @dev Imitates a Solidity high-level call (i.e. a regular function call to a contract), relaxing the requirement - * on the return value: the return value is optional (but if data is returned, it must not be false). - * @param token The token targeted by the call. - * @param data The call data (encoded using abi.encode or one of its variants). - */ - function _callOptionalReturn(IERC20 token, bytes memory data) private { - // We need to perform a low level call here, to bypass Solidity's return data size checking mechanism, since - // we're implementing it ourselves. We use {Address.functionCall} to perform this call, which verifies that - // the target address contains contract code and also asserts for success in the low-level call. - - bytes memory returndata = address(token).functionCall(data, "SafeERC20: low-level call failed"); - if (returndata.length > 0) { - // Return data is optional - require(abi.decode(returndata, (bool)), "SafeERC20: ERC20 operation did not succeed"); - } - } -} - - - - - - - - - - - - - - -/** - * @dev Provides information about the current execution context, including the - * sender of the transaction and its data. While these are generally available - * via msg.sender and msg.data, they should not be accessed in such a direct - * manner, since when dealing with meta-transactions the account sending and - * paying for execution may not be the actual sender (as far as an application - * is concerned). - * - * This contract is only required for intermediate, library-like contracts. - */ -abstract contract Context { - function _msgSender() internal view virtual returns (address) { - return msg.sender; - } - - function _msgData() internal view virtual returns (bytes calldata) { - return msg.data; - } -} - - -/** - * @dev Contract module which provides a basic access control mechanism, where - * there is an account (an owner) that can be granted exclusive access to - * specific functions. - * - * By default, the owner account will be the one that deploys the contract. This - * can later be changed with {transferOwnership}. - * - * This module is used through inheritance. It will make available the modifier - * `onlyOwner`, which can be applied to your functions to restrict their use to - * the owner. - */ -abstract contract Ownable is Context { - address private _owner; - - event OwnershipTransferred(address indexed previousOwner, address indexed newOwner); - - /** - * @dev Initializes the contract setting the deployer as the initial owner. - */ - constructor() { - _transferOwnership(_msgSender()); - } - - /** - * @dev Throws if called by any account other than the owner. - */ - modifier onlyOwner() { - _checkOwner(); - _; - } - - /** - * @dev Returns the address of the current owner. - */ - function owner() public view virtual returns (address) { - return _owner; - } - - /** - * @dev Throws if the sender is not the owner. - */ - function _checkOwner() internal view virtual { - require(owner() == _msgSender(), "Ownable: caller is not the owner"); - } - - /** - * @dev Leaves the contract without owner. It will not be possible to call - * `onlyOwner` functions anymore. Can only be called by the current owner. - * - * NOTE: Renouncing ownership will leave the contract without an owner, - * thereby removing any functionality that is only available to the owner. - */ - function renounceOwnership() public virtual onlyOwner { - _transferOwnership(address(0)); - } - - /** - * @dev Transfers ownership of the contract to a new account (`newOwner`). - * Can only be called by the current owner. - */ - function transferOwnership(address newOwner) public virtual onlyOwner { - require(newOwner != address(0), "Ownable: new owner is the zero address"); - _transferOwnership(newOwner); - } - - /** - * @dev Transfers ownership of the contract to a new account (`newOwner`). - * Internal function without access restriction. - */ - function _transferOwnership(address newOwner) internal virtual { - address oldOwner = _owner; - _owner = newOwner; - emit OwnershipTransferred(oldOwner, newOwner); - } -} - - -contract Operator is Ownable { - address public operator; - uint256 constant baseRate = 10000; - - modifier onlyOperator { - require(msg.sender == owner() || msg.sender == operator, "no permission"); - _; - } - - function setOperator(address operator_) external onlyOwner { - operator = operator_; - } - - - function getCurrTime() external view returns(uint256) { - return block.timestamp; - } - - function getBlockNum() external view returns(uint256) { - return block.number; - } - -} - - - - - -/** - * @dev Library for managing - * https://en.wikipedia.org/wiki/Set_(abstract_data_type)[sets] of primitive - * types. - * - * Sets have the following properties: - * - * - Elements are added, removed, and checked for existence in constant time - * (O(1)). - * - Elements are enumerated in O(n). No guarantees are made on the ordering. - * - * ``` - * contract Example { - * // Add the library methods - * using EnumerableSet for EnumerableSet.AddressSet; - * - * // Declare a set state variable - * EnumerableSet.AddressSet private mySet; - * } - * ``` - * - * As of v3.3.0, sets of type `bytes32` (`Bytes32Set`), `address` (`AddressSet`) - * and `uint256` (`UintSet`) are supported. - * - * [WARNING] - * ==== - * Trying to delete such a structure from storage will likely result in data corruption, rendering the structure unusable. - * See https://github.com/ethereum/solidity/pull/11843[ethereum/solidity#11843] for more info. - * - * In order to clean an EnumerableSet, you can either remove all elements one by one or create a fresh instance using an array of EnumerableSet. - * ==== - */ - -library EnumerableSet { - // To implement this library for multiple types with as little code - // repetition as possible, we write it in terms of a generic Set type with - // bytes32 values. - // The Set implementation uses private functions, and user-facing - // implementations (such as AddressSet) are just wrappers around the - // underlying Set. - // This means that we can only create new EnumerableSets for types that fit - // in bytes32. - - struct Set { - // Storage of set values - bytes32[] _values; - // Position of the value in the `values` array, plus 1 because index 0 - // means a value is not in the set. - mapping(bytes32 => uint256) _indexes; - } - - /** - * @dev Add a value to a set. O(1). - * - * Returns true if the value was added to the set, that is if it was not - * already present. - */ - function _add(Set storage set, bytes32 value) private returns (bool) { - if (!_contains(set, value)) { - set._values.push(value); - // The value is stored at length-1, but we add 1 to all indexes - // and use 0 as a sentinel value - set._indexes[value] = set._values.length; - return true; - } else { - return false; - } - } - - /** - * @dev Removes a value from a set. O(1). - * - * Returns true if the value was removed from the set, that is if it was - * present. - */ - function _remove(Set storage set, bytes32 value) private returns (bool) { - // We read and store the value's index to prevent multiple reads from the same storage slot - uint256 valueIndex = set._indexes[value]; - - if (valueIndex != 0) { - // Equivalent to contains(set, value) - // To delete an element from the _values array in O(1), we swap the element to delete with the last one in - // the array, and then remove the last element (sometimes called as 'swap and pop'). - // This modifies the order of the array, as noted in {at}. - - uint256 toDeleteIndex = valueIndex - 1; - uint256 lastIndex = set._values.length - 1; - - if (lastIndex != toDeleteIndex) { - bytes32 lastValue = set._values[lastIndex]; - - // Move the last value to the index where the value to delete is - set._values[toDeleteIndex] = lastValue; - // Update the index for the moved value - set._indexes[lastValue] = valueIndex; // Replace lastValue's index to valueIndex - } - - // Delete the slot where the moved value was stored - set._values.pop(); - - // Delete the index for the deleted slot - delete set._indexes[value]; - - return true; - } else { - return false; - } - } - - /** - * @dev Returns true if the value is in the set. O(1). - */ - function _contains(Set storage set, bytes32 value) private view returns (bool) { - return set._indexes[value] != 0; - } - - /** - * @dev Returns the number of values on the set. O(1). - */ - function _length(Set storage set) private view returns (uint256) { - return set._values.length; - } - - /** - * @dev Returns the value stored at position `index` in the set. O(1). - * - * Note that there are no guarantees on the ordering of values inside the - * array, and it may change when more values are added or removed. - * - * Requirements: - * - * - `index` must be strictly less than {length}. - */ - function _at(Set storage set, uint256 index) private view returns (bytes32) { - return set._values[index]; - } - - /** - * @dev Return the entire set in an array - * - * WARNING: This operation will copy the entire storage to memory, which can be quite expensive. This is designed - * to mostly be used by view accessors that are queried without any gas fees. Developers should keep in mind that - * this function has an unbounded cost, and using it as part of a state-changing function may render the function - * uncallable if the set grows to a point where copying to memory consumes too much gas to fit in a block. - */ - function _values(Set storage set) private view returns (bytes32[] memory) { - return set._values; - } - - // Bytes32Set - - struct Bytes32Set { - Set _inner; - } - - /** - * @dev Add a value to a set. O(1). - * - * Returns true if the value was added to the set, that is if it was not - * already present. - */ - function add(Bytes32Set storage set, bytes32 value) internal returns (bool) { - return _add(set._inner, value); - } - - /** - * @dev Removes a value from a set. O(1). - * - * Returns true if the value was removed from the set, that is if it was - * present. - */ - function remove(Bytes32Set storage set, bytes32 value) internal returns (bool) { - return _remove(set._inner, value); - } - - /** - * @dev Returns true if the value is in the set. O(1). - */ - function contains(Bytes32Set storage set, bytes32 value) internal view returns (bool) { - return _contains(set._inner, value); - } - - /** - * @dev Returns the number of values in the set. O(1). - */ - function length(Bytes32Set storage set) internal view returns (uint256) { - return _length(set._inner); - } - - /** - * @dev Returns the value stored at position `index` in the set. O(1). - * - * Note that there are no guarantees on the ordering of values inside the - * array, and it may change when more values are added or removed. - * - * Requirements: - * - * - `index` must be strictly less than {length}. - */ - function at(Bytes32Set storage set, uint256 index) internal view returns (bytes32) { - return _at(set._inner, index); - } - - /** - * @dev Return the entire set in an array - * - * WARNING: This operation will copy the entire storage to memory, which can be quite expensive. This is designed - * to mostly be used by view accessors that are queried without any gas fees. Developers should keep in mind that - * this function has an unbounded cost, and using it as part of a state-changing function may render the function - * uncallable if the set grows to a point where copying to memory consumes too much gas to fit in a block. - */ - function values(Bytes32Set storage set) internal view returns (bytes32[] memory) { - return _values(set._inner); - } - - // AddressSet - - struct AddressSet { - Set _inner; - } - - /** - * @dev Add a value to a set. O(1). - * - * Returns true if the value was added to the set, that is if it was not - * already present. - */ - function add(AddressSet storage set, address value) internal returns (bool) { - return _add(set._inner, bytes32(uint256(uint160(value)))); - } - - /** - * @dev Removes a value from a set. O(1). - * - * Returns true if the value was removed from the set, that is if it was - * present. - */ - function remove(AddressSet storage set, address value) internal returns (bool) { - return _remove(set._inner, bytes32(uint256(uint160(value)))); - } - - /** - * @dev Returns true if the value is in the set. O(1). - */ - function contains(AddressSet storage set, address value) internal view returns (bool) { - return _contains(set._inner, bytes32(uint256(uint160(value)))); - } - - /** - * @dev Returns the number of values in the set. O(1). - */ - function length(AddressSet storage set) internal view returns (uint256) { - return _length(set._inner); - } - - /** - * @dev Returns the value stored at position `index` in the set. O(1). - * - * Note that there are no guarantees on the ordering of values inside the - * array, and it may change when more values are added or removed. - * - * Requirements: - * - * - `index` must be strictly less than {length}. - */ - function at(AddressSet storage set, uint256 index) internal view returns (address) { - return address(uint160(uint256(_at(set._inner, index)))); - } - - /** - * @dev Return the entire set in an array - * - * WARNING: This operation will copy the entire storage to memory, which can be quite expensive. This is designed - * to mostly be used by view accessors that are queried without any gas fees. Developers should keep in mind that - * this function has an unbounded cost, and using it as part of a state-changing function may render the function - * uncallable if the set grows to a point where copying to memory consumes too much gas to fit in a block. - */ - function values(AddressSet storage set) internal view returns (address[] memory) { - bytes32[] memory store = _values(set._inner); - address[] memory result; - - /// @solidity memory-safe-assembly - assembly { - result := store - } - - return result; - } - - // UintSet - - struct UintSet { - Set _inner; - } - - /** - * @dev Add a value to a set. O(1). - * - * Returns true if the value was added to the set, that is if it was not - * already present. - */ - function add(UintSet storage set, uint256 value) internal returns (bool) { - return _add(set._inner, bytes32(value)); - } - - /** - * @dev Removes a value from a set. O(1). - * - * Returns true if the value was removed from the set, that is if it was - * present. - */ - function remove(UintSet storage set, uint256 value) internal returns (bool) { - return _remove(set._inner, bytes32(value)); - } - - /** - * @dev Returns true if the value is in the set. O(1). - */ - function contains(UintSet storage set, uint256 value) internal view returns (bool) { - return _contains(set._inner, bytes32(value)); - } - - /** - * @dev Returns the number of values on the set. O(1). - */ - function length(UintSet storage set) internal view returns (uint256) { - return _length(set._inner); - } - - /** - * @dev Returns the value stored at position `index` in the set. O(1). - * - * Note that there are no guarantees on the ordering of values inside the - * array, and it may change when more values are added or removed. - * - * Requirements: - * - * - `index` must be strictly less than {length}. - */ - function at(UintSet storage set, uint256 index) internal view returns (uint256) { - return uint256(_at(set._inner, index)); - } - - /** - * @dev Return the entire set in an array - * - * WARNING: This operation will copy the entire storage to memory, which can be quite expensive. This is designed - * to mostly be used by view accessors that are queried without any gas fees. Developers should keep in mind that - * this function has an unbounded cost, and using it as part of a state-changing function may render the function - * uncallable if the set grows to a point where copying to memory consumes too much gas to fit in a block. - */ - function values(UintSet storage set) internal view returns (uint256[] memory) { - bytes32[] memory store = _values(set._inner); - uint256[] memory result; - - /// @solidity memory-safe-assembly - assembly { - result := store - } - - return result; - } -} - - -contract ActivityPool is Operator { - using SafeMath for uint256; - using SafeERC20 for IERC20; - using EnumerableSet for EnumerableSet.AddressSet; - using EnumerableSet for EnumerableSet.UintSet; - - event AddNewAct(uint256 id); - event Bet(address user, uint256 pID, uint256 bType, uint256 amount, uint256 time); - event SetPrize(uint256 pID, uint256 bType); - event Claim(address user, uint256 pID, uint256 bType, uint256 amount); - event RemovePeriodAct(uint256 pID); - - uint256 public constant muti = 1e18; - uint256 public periodID; - uint256 public betID; - - struct UserInfo { - address user; - uint256 pID; - uint256 amount; - uint256 betTime; - uint256 bType; - uint256 claimAmount; - } - - struct ActInfo { - string name; - string aName; - string bName; - address rewardToken; - uint256 startTime; - uint256 endTime; - uint256 minAmount; - uint256 maxAmount; - uint256 aAmount; - uint256 bAmount; - uint256 winType; - bool isBet; - } - - struct TimeInfo { - uint256 time; - uint256 aAmount; - uint256 bAmount; - } - - struct BestInfo { - address aUser; - address bUser; - uint256 aBet; - uint256 bBet; - } - - mapping(uint256 => BestInfo) bestInfo; - mapping(uint256 => uint256) public timeID; - mapping(uint256 => mapping(uint256 => TimeInfo)) public timeInfo; - mapping(address => mapping(uint256 => uint256)) public userBet; - mapping(uint256 => UserInfo) public betInfo; - mapping(uint256 => uint256) public perAmount; - mapping(uint256 => ActInfo) public actInfo; - mapping(uint256 => mapping(uint256 => string)) public descripName; - - mapping(address => EnumerableSet.UintSet) userPid; - mapping(uint256 => EnumerableSet.AddressSet) aUsers; - mapping(uint256 => EnumerableSet.AddressSet) bUsers; - EnumerableSet.UintSet activePeriod; - EnumerableSet.UintSet removePeriod; - - function addNewAct( - string memory name, - string memory aName, - string memory bName, - address token, - uint256 startTime, - uint256 endTime, - uint256 minAmount, - uint256 maxAmount - ) external onlyOperator { - - checkAdd(msg.sender, startTime, endTime, minAmount, maxAmount); - uint256 id = ++periodID; - actInfo[id].name = name; - actInfo[id].aName = aName; - actInfo[id].bName = bName; - actInfo[id].startTime = startTime; - actInfo[id].endTime = endTime; - actInfo[id].minAmount = minAmount; - actInfo[id].maxAmount = maxAmount; - actInfo[id].rewardToken = token; - descripName[id][1] = aName; - descripName[id][2] = bName; - activePeriod.add(id); - - emit AddNewAct(id); - } - - - function removePeriodAct(uint256 pID) external onlyOperator { - checkRemove(pID); - - activePeriod.remove(pID); - removePeriod.add(pID); - - emit RemovePeriodAct(pID); - } - - - function bet(uint256 pID, uint256 bType, uint256 amount) external payable { - checkBet(msg.sender, pID, bType, amount); - if(actInfo[pID].rewardToken == address(0)) { - require(msg.value == amount, "value err"); - } else { - require(msg.value == 0, "value amount err"); - } - - if(bType == 1) { - if(amount > bestInfo[pID].aBet) { - bestInfo[pID].aUser = msg.sender; - bestInfo[pID].aBet = amount; - } - } else { - if(amount > bestInfo[pID].bBet) { - bestInfo[pID].bUser = msg.sender; - bestInfo[pID].bBet = amount; - } - } - - userPid[msg.sender].add(pID); - uint256 id = ++betID; - userBet[msg.sender][pID] = id; - - if(bType == 1) { - aUsers[pID].add(msg.sender); - actInfo[pID].aAmount = actInfo[pID].aAmount.add(amount); - } else { - bUsers[pID].add(msg.sender); - actInfo[pID].bAmount = actInfo[pID].bAmount.add(amount); - } - - actInfo[pID].isBet = true; - betInfo[id].user = msg.sender; - betInfo[id].pID = pID; - betInfo[id].amount = amount; - betInfo[id].betTime = block.timestamp; - betInfo[id].bType = bType; - - uint256 tID = ++timeID[pID]; - timeInfo[pID][tID].time = block.timestamp; - timeInfo[pID][tID].aAmount = actInfo[pID].aAmount; - timeInfo[pID][tID].bAmount = actInfo[pID].bAmount; - - if(actInfo[pID].rewardToken != address(0)) { - IERC20(actInfo[pID].rewardToken).safeTransferFrom(msg.sender, address(this), amount); - } - emit Bet(msg.sender, pID, bType, amount, betInfo[id].betTime); - } - - function setPrize(uint256 pID, uint256 bType) external onlyOperator { - checkSetPrize(msg.sender, pID, bType); - - if(block.timestamp <= actInfo[pID].startTime) { - actInfo[pID].startTime = block.timestamp; - - } - actInfo[pID].endTime = block.timestamp; - - actInfo[pID].winType = bType; - perAmount[pID] = getPerAmount(pID, bType); - - emit SetPrize(pID, bType); - } - - function recive() public payable {} - - function claim(uint256 pID) external { - uint256 amount = checkClaim(msg.sender, pID); - - uint256 id = userBet[msg.sender][pID]; - betInfo[id].claimAmount = amount; - if(actInfo[pID].rewardToken != address(0)) { - IERC20(actInfo[pID].rewardToken).safeTransfer(msg.sender, amount); - } else { - payable(msg.sender).transfer(amount); - } - - emit Claim(msg.sender, pID, betInfo[id].bType, amount); - } - - function checkClaim(address user, uint256 pID) public view returns(uint256 amount) { - require(userPid[user].contains(pID), "not bet"); - uint256 id = userBet[user][pID]; - require(betInfo[id].user == user, "not user"); - require(actInfo[pID].winType != 0, "not prize"); - require(betInfo[id].claimAmount == 0, "has claim"); - - if(actInfo[pID].winType != 3) { - require(actInfo[pID].winType == betInfo[id].bType, "not right"); - amount = perAmount[pID].mul(betInfo[id].amount).div(muti); - require(amount > 0, "no amount"); - } else { - amount = betInfo[id].amount; - } - - return amount; - } - - function getActualRate( - address user, - uint256 pID, - uint256 bType, - uint256 amount - ) external view returns(uint256, uint256, bool) { - if(bType < 1 || bType > 2 || !activePeriod.contains(pID)) { - return (0, 0, false); - } else if(userBet[user][pID] != 0 || actInfo[pID].winType != 0 || amount == 0) { - (uint256 ra, uint256 rb) = getRate(pID, timeID[pID]); - return (ra, rb, false); - } else { - (uint256 aAmount, uint256 bAmount) = (actInfo[pID].aAmount, actInfo[pID].bAmount); - if(bType == 1) { - aAmount = aAmount.add(amount); - } else { - bAmount = bAmount.add(amount); - } - - uint256 total = aAmount.add(bAmount); - if(bAmount == 0 && aAmount != 0) { - return (muti, 0, true); - } - if(bAmount != 0 && aAmount == 0) { - return (0, muti, true); - } - return (total.mul(muti).div(aAmount), total.mul(muti).div(bAmount), true); - } - } - - function getRate(uint256 pID, uint256 tID) public view returns(uint256, uint256) { - (uint256 aAmount, uint256 bAmount) = (timeInfo[pID][tID].aAmount, timeInfo[pID][tID].bAmount); - uint256 total = aAmount.add(bAmount); - if(total == 0) { - return (0, 0); - } - if(bAmount == 0 && aAmount != 0) { - return (muti, 0); - } - if(bAmount != 0 && aAmount == 0) { - return (0, muti); - } - return (total.mul(muti).div(aAmount), total.mul(muti).div(bAmount)); - } - - function getBestInfo(uint256 pID) - external - view - returns(address aUser, address bUser, uint256 aBet, uint256 bBet, uint256 aReward, uint256 bReward) - { - aUser = bestInfo[pID].aUser; - bUser = bestInfo[pID].bUser; - aBet = bestInfo[pID].aBet; - bBet = bestInfo[pID].bBet; - aReward = getPerAmount(pID, 1).mul(aBet).div(muti); - bReward = getPerAmount(pID, 2).mul(bBet).div(muti); - } - - function getPerAmount(uint256 pID, uint256 bType) public view returns(uint256) { - uint256 total = actInfo[pID].aAmount.add(actInfo[pID].bAmount); - if(total == 0) { - return 0; - } - - if(actInfo[pID].winType == 3) { - return muti; - } - - if(bType == 1) { - if(actInfo[pID].aAmount == 0 || actInfo[pID].winType == 2) { - return 0; - } - return total.mul(muti).div(actInfo[pID].aAmount); - } - - if(bType == 2) { - if(actInfo[pID].bAmount == 0 || actInfo[pID].winType == 1) { - return 0; - } - return total.mul(muti).div(actInfo[pID].bAmount); - } - - return 0; - - } - - function checkSetPrize(address user, uint256 pID, uint256 bType) public view returns(bool) { - require(user == owner() || user == operator, "no permission"); - require(bType > 0 && bType <= 3, "type err"); - require(activePeriod.contains(pID), "not active"); - require(actInfo[pID].winType == 0, "has set"); - - return true; - } - - function checkBet( - address user, - uint256 pID, - uint256 bType, - uint256 amount - ) public view returns(bool) { - require(activePeriod.contains(pID), "not active"); - require(actInfo[pID].startTime <= block.timestamp, "not start"); - require(actInfo[pID].endTime > block.timestamp, "has end"); - require(!userPid[user].contains(pID), "has bet"); - require(bType > 0 && bType < 3, "type err"); - require(amount >= actInfo[pID].minAmount && amount <= actInfo[pID].maxAmount, "amount err"); - if(actInfo[pID].rewardToken != address(0)) { - require(IERC20(actInfo[pID].rewardToken).allowance(user, address(this)) >= amount, "not approve enough"); - require(IERC20(actInfo[pID].rewardToken).balanceOf(user) >= amount, "not enough"); - } else { - require(user.balance >= amount, "main token err"); - } - - return true; - } - - - function checkRemove(uint256 pID) public view returns(bool) { - require(activePeriod.contains(pID), "not in"); - require(!actInfo[pID].isBet, "has bet"); - - return true; - } - - function checkAdd( - address user, - uint256 startTime, - uint256 endTime, - uint256 minAmount, - uint256 maxAmount - ) public view returns(bool) { - require(user == owner() || user == operator, "no permission"); - require(startTime > block.timestamp, "startTime err"); - require(endTime > startTime, "endTime err"); - require(minAmount > 0 && maxAmount > minAmount, "amount err"); - - return true; - } - - function getStatus(uint256 pID) external view returns(uint256) { - if(!removePeriod.contains(pID) && !activePeriod.contains(pID)) { - return 5; - } else if(removePeriod.contains(pID)) { - return 6; - } else if(block.timestamp < actInfo[pID].startTime) { - return 1; - } else if ( - actInfo[pID].startTime <= block.timestamp && - actInfo[pID].endTime > block.timestamp - ) { - return 2; - } else if (actInfo[pID].endTime <= block.timestamp && actInfo[pID].winType == 0){ - return 3; - } else if(actInfo[pID].winType != 0) { - return 4; - } - return 0; - } - - function getUserPidNum(address user) external view returns(uint256) { - return userPid[user].length(); - } - - function getUserPid(address user, uint256 index) external view returns(uint256) { - return userPid[user].at(index); - } - - function getAUsersNum(uint256 pID) external view returns(uint256) { - return aUsers[pID].length(); - } - - function getAUsers(uint256 pID, uint256 index) external view returns(address) { - return aUsers[pID].at(index); - } - - function getBUsersNum(uint256 pID) external view returns(uint256) { - return bUsers[pID].length(); - } - - function getBUsers(uint256 pID, uint256 index) external view returns(address) { - return bUsers[pID].at(index); - } - - function getActivePeriodNum() external view returns(uint256) { - return activePeriod.length(); - } - - function getActivePeriod(uint256 index) external view returns(uint256) { - return activePeriod.at(index); - } - - function getRemovePeriodNum() external view returns(uint256) { - return removePeriod.length(); - } - - function getRemovePeriod(uint256 index) external view returns(uint256) { - return removePeriod.at(index); - } -} \ No newline at end of file diff --git a/app/api/uploads/ActivityPool-1729824663495-208623935.sol b/app/api/uploads/ActivityPool-1729824663495-208623935.sol deleted file mode 100644 index daf3372..0000000 --- a/app/api/uploads/ActivityPool-1729824663495-208623935.sol +++ /dev/null @@ -1,1648 +0,0 @@ -// SPDX-License-Identifier: MIT -// OpenZeppelin Contracts (last updated v4.7.0) (utils/Address.sol) - -pragma solidity ^0.8.1; - -/** - * @dev Collection of functions related to the address type - */ -library Address { - /** - * @dev Returns true if `account` is a contract. - * - * [IMPORTANT] - * ==== - * It is unsafe to assume that an address for which this function returns - * false is an externally-owned account (EOA) and not a contract. - * - * Among others, `isContract` will return false for the following - * types of addresses: - * - * - an externally-owned account - * - a contract in construction - * - an address where a contract will be created - * - an address where a contract lived, but was destroyed - * ==== - * - * [IMPORTANT] - * ==== - * You shouldn't rely on `isContract` to protect against flash loan attacks! - * - * Preventing calls from contracts is highly discouraged. It breaks composability, breaks support for smart wallets - * like Gnosis Safe, and does not provide security since it can be circumvented by calling from a contract - * constructor. - * ==== - */ - function isContract(address account) internal view returns (bool) { - // This method relies on extcodesize/address.code.length, which returns 0 - // for contracts in construction, since the code is only stored at the end - // of the constructor execution. - - return account.code.length > 0; - } - - /** - * @dev Replacement for Solidity's `transfer`: sends `amount` wei to - * `recipient`, forwarding all available gas and reverting on errors. - * - * https://eips.ethereum.org/EIPS/eip-1884[EIP1884] increases the gas cost - * of certain opcodes, possibly making contracts go over the 2300 gas limit - * imposed by `transfer`, making them unable to receive funds via - * `transfer`. {sendValue} removes this limitation. - * - * https://diligence.consensys.net/posts/2019/09/stop-using-soliditys-transfer-now/[Learn more]. - * - * IMPORTANT: because control is transferred to `recipient`, care must be - * taken to not create reentrancy vulnerabilities. Consider using - * {ReentrancyGuard} or the - * https://solidity.readthedocs.io/en/v0.5.11/security-considerations.html#use-the-checks-effects-interactions-pattern[checks-effects-interactions pattern]. - */ - function sendValue(address payable recipient, uint256 amount) internal { - require(address(this).balance >= amount, "Address: insufficient balance"); - - (bool success, ) = recipient.call{value: amount}(""); - require(success, "Address: unable to send value, recipient may have reverted"); - } - - /** - * @dev Performs a Solidity function call using a low level `call`. A - * plain `call` is an unsafe replacement for a function call: use this - * function instead. - * - * If `target` reverts with a revert reason, it is bubbled up by this - * function (like regular Solidity function calls). - * - * Returns the raw returned data. To convert to the expected return value, - * use https://solidity.readthedocs.io/en/latest/units-and-global-variables.html?highlight=abi.decode#abi-encoding-and-decoding-functions[`abi.decode`]. - * - * Requirements: - * - * - `target` must be a contract. - * - calling `target` with `data` must not revert. - * - * _Available since v3.1._ - */ - function functionCall(address target, bytes memory data) internal returns (bytes memory) { - return functionCallWithValue(target, data, 0, "Address: low-level call failed"); - } - - /** - * @dev Same as {xref-Address-functionCall-address-bytes-}[`functionCall`], but with - * `errorMessage` as a fallback revert reason when `target` reverts. - * - * _Available since v3.1._ - */ - function functionCall( - address target, - bytes memory data, - string memory errorMessage - ) internal returns (bytes memory) { - return functionCallWithValue(target, data, 0, errorMessage); - } - - /** - * @dev Same as {xref-Address-functionCall-address-bytes-}[`functionCall`], - * but also transferring `value` wei to `target`. - * - * Requirements: - * - * - the calling contract must have an ETH balance of at least `value`. - * - the called Solidity function must be `payable`. - * - * _Available since v3.1._ - */ - function functionCallWithValue( - address target, - bytes memory data, - uint256 value - ) internal returns (bytes memory) { - return functionCallWithValue(target, data, value, "Address: low-level call with value failed"); - } - - /** - * @dev Same as {xref-Address-functionCallWithValue-address-bytes-uint256-}[`functionCallWithValue`], but - * with `errorMessage` as a fallback revert reason when `target` reverts. - * - * _Available since v3.1._ - */ - function functionCallWithValue( - address target, - bytes memory data, - uint256 value, - string memory errorMessage - ) internal returns (bytes memory) { - require(address(this).balance >= value, "Address: insufficient balance for call"); - (bool success, bytes memory returndata) = target.call{value: value}(data); - return verifyCallResultFromTarget(target, success, returndata, errorMessage); - } - - /** - * @dev Same as {xref-Address-functionCall-address-bytes-}[`functionCall`], - * but performing a static call. - * - * _Available since v3.3._ - */ - function functionStaticCall(address target, bytes memory data) internal view returns (bytes memory) { - return functionStaticCall(target, data, "Address: low-level static call failed"); - } - - /** - * @dev Same as {xref-Address-functionCall-address-bytes-string-}[`functionCall`], - * but performing a static call. - * - * _Available since v3.3._ - */ - function functionStaticCall( - address target, - bytes memory data, - string memory errorMessage - ) internal view returns (bytes memory) { - (bool success, bytes memory returndata) = target.staticcall(data); - return verifyCallResultFromTarget(target, success, returndata, errorMessage); - } - - /** - * @dev Same as {xref-Address-functionCall-address-bytes-}[`functionCall`], - * but performing a delegate call. - * - * _Available since v3.4._ - */ - function functionDelegateCall(address target, bytes memory data) internal returns (bytes memory) { - return functionDelegateCall(target, data, "Address: low-level delegate call failed"); - } - - /** - * @dev Same as {xref-Address-functionCall-address-bytes-string-}[`functionCall`], - * but performing a delegate call. - * - * _Available since v3.4._ - */ - function functionDelegateCall( - address target, - bytes memory data, - string memory errorMessage - ) internal returns (bytes memory) { - (bool success, bytes memory returndata) = target.delegatecall(data); - return verifyCallResultFromTarget(target, success, returndata, errorMessage); - } - - /** - * @dev Tool to verify that a low level call to smart-contract was successful, and revert (either by bubbling - * the revert reason or using the provided one) in case of unsuccessful call or if target was not a contract. - * - * _Available since v4.8._ - */ - function verifyCallResultFromTarget( - address target, - bool success, - bytes memory returndata, - string memory errorMessage - ) internal view returns (bytes memory) { - if (success) { - if (returndata.length == 0) { - // only check isContract if the call was successful and the return data is empty - // otherwise we already know that it was a contract - require(isContract(target), "Address: call to non-contract"); - } - return returndata; - } else { - _revert(returndata, errorMessage); - } - } - - /** - * @dev Tool to verify that a low level call was successful, and revert if it wasn't, either by bubbling the - * revert reason or using the provided one. - * - * _Available since v4.3._ - */ - function verifyCallResult( - bool success, - bytes memory returndata, - string memory errorMessage - ) internal pure returns (bytes memory) { - if (success) { - return returndata; - } else { - _revert(returndata, errorMessage); - } - } - - function _revert(bytes memory returndata, string memory errorMessage) private pure { - // Look for revert reason and bubble it up if present - if (returndata.length > 0) { - // The easiest way to bubble the revert reason is using memory via assembly - /// @solidity memory-safe-assembly - assembly { - let returndata_size := mload(returndata) - revert(add(32, returndata), returndata_size) - } - } else { - revert(errorMessage); - } - } -} - -// OpenZeppelin Contracts (last updated v4.6.0) (token/ERC20/IERC20.sol) - - - -/** - * @dev Interface of the ERC20 standard as defined in the EIP. - */ -interface IERC20 { - /** - * @dev Emitted when `value` tokens are moved from one account (`from`) to - * another (`to`). - * - * Note that `value` may be zero. - */ - event Transfer(address indexed from, address indexed to, uint256 value); - - /** - * @dev Emitted when the allowance of a `spender` for an `owner` is set by - * a call to {approve}. `value` is the new allowance. - */ - event Approval(address indexed owner, address indexed spender, uint256 value); - - /** - * @dev Returns the amount of tokens in existence. - */ - function totalSupply() external view returns (uint256); - - /** - * @dev Returns the amount of tokens owned by `account`. - */ - function balanceOf(address account) external view returns (uint256); - - /** - * @dev Moves `amount` tokens from the caller's account to `to`. - * - * Returns a boolean value indicating whether the operation succeeded. - * - * Emits a {Transfer} event. - */ - function transfer(address to, uint256 amount) external returns (bool); - - /** - * @dev Returns the remaining number of tokens that `spender` will be - * allowed to spend on behalf of `owner` through {transferFrom}. This is - * zero by default. - * - * This value changes when {approve} or {transferFrom} are called. - */ - function allowance(address owner, address spender) external view returns (uint256); - - /** - * @dev Sets `amount` as the allowance of `spender` over the caller's tokens. - * - * Returns a boolean value indicating whether the operation succeeded. - * - * IMPORTANT: Beware that changing an allowance with this method brings the risk - * that someone may use both the old and the new allowance by unfortunate - * transaction ordering. One possible solution to mitigate this race - * condition is to first reduce the spender's allowance to 0 and set the - * desired value afterwards: - * https://github.com/ethereum/EIPs/issues/20#issuecomment-263524729 - * - * Emits an {Approval} event. - */ - function approve(address spender, uint256 amount) external returns (bool); - - /** - * @dev Moves `amount` tokens from `from` to `to` using the - * allowance mechanism. `amount` is then deducted from the caller's - * allowance. - * - * Returns a boolean value indicating whether the operation succeeded. - * - * Emits a {Transfer} event. - */ - function transferFrom( - address from, - address to, - uint256 amount - ) external returns (bool); - - - function mint(address account_, uint256 amount_) external; - - function burn(uint256 amount) external; - -} - - - - - - - - - - - -/** - * @dev Wrappers over Solidity's arithmetic operations with added overflow - * checks. - * - * Arithmetic operations in Solidity wrap on overflow. This can easily result - * in bugs, because programmers usually assume that an overflow raises an - * error, which is the standard behavior in high level programming languages. - * `SafeMath` restores this intuition by reverting the transaction when an - * operation overflows. - * - * Using this library instead of the unchecked operations eliminates an entire - * class of bugs, so it's recommended to use it always. - */ -library SafeMath { - /** - * @dev Returns the addition of two unsigned integers, reverting on - * overflow. - * - * Counterpart to Solidity's `+` operator. - * - * Requirements: - * - * - Addition cannot overflow. - */ - function add(uint256 a, uint256 b) internal pure returns (uint256) { - uint256 c = a + b; - require(c >= a, "SafeMath: addition overflow"); - - return c; - } - - /** - * @dev Returns the subtraction of two unsigned integers, reverting on - * overflow (when the result is negative). - * - * Counterpart to Solidity's `-` operator. - * - * Requirements: - * - * - Subtraction cannot overflow. - */ - function sub(uint256 a, uint256 b) internal pure returns (uint256) { - return sub(a, b, "SafeMath: subtraction overflow"); - } - - /** - * @dev Returns the subtraction of two unsigned integers, reverting with custom message on - * overflow (when the result is negative). - * - * Counterpart to Solidity's `-` operator. - * - * Requirements: - * - * - Subtraction cannot overflow. - */ - function sub( - uint256 a, - uint256 b, - string memory errorMessage - ) internal pure returns (uint256) { - require(b <= a, errorMessage); - uint256 c = a - b; - - return c; - } - - /** - * @dev Returns the multiplication of two unsigned integers, reverting on - * overflow. - * - * Counterpart to Solidity's `*` operator. - * - * Requirements: - * - * - Multiplication cannot overflow. - */ - function mul(uint256 a, uint256 b) internal pure returns (uint256) { - // Gas optimization: this is cheaper than requiring 'a' not being zero, but the - // benefit is lost if 'b' is also tested. - // See: https://github.com/OpenZeppelin/openzeppelin-contracts/pull/522 - if (a == 0) { - return 0; - } - - uint256 c = a * b; - require(c / a == b, "SafeMath: multiplication overflow"); - - return c; - } - - /** - * @dev Returns the integer division of two unsigned integers. Reverts on - * division by zero. The result is rounded towards zero. - * - * Counterpart to Solidity's `/` operator. Note: this function uses a - * `revert` opcode (which leaves remaining gas untouched) while Solidity - * uses an invalid opcode to revert (consuming all remaining gas). - * - * Requirements: - * - * - The divisor cannot be zero. - */ - function div(uint256 a, uint256 b) internal pure returns (uint256) { - return div(a, b, "SafeMath: division by zero"); - } - - /** - * @dev Returns the integer division of two unsigned integers. Reverts with custom message on - * division by zero. The result is rounded towards zero. - * - * Counterpart to Solidity's `/` operator. Note: this function uses a - * `revert` opcode (which leaves remaining gas untouched) while Solidity - * uses an invalid opcode to revert (consuming all remaining gas). - * - * Requirements: - * - * - The divisor cannot be zero. - */ - function div( - uint256 a, - uint256 b, - string memory errorMessage - ) internal pure returns (uint256) { - require(b > 0, errorMessage); - uint256 c = a / b; - // assert(a == b * c + a % b); // There is no case in which this doesn't hold - - return c; - } - - /** - * @dev Returns the remainder of dividing two unsigned integers. (unsigned integer modulo), - * Reverts when dividing by zero. - * - * Counterpart to Solidity's `%` operator. This function uses a `revert` - * opcode (which leaves remaining gas untouched) while Solidity uses an - * invalid opcode to revert (consuming all remaining gas). - * - * Requirements: - * - * - The divisor cannot be zero. - */ - function mod(uint256 a, uint256 b) internal pure returns (uint256) { - return mod(a, b, "SafeMath: modulo by zero"); - } - - /** - * @dev Returns the remainder of dividing two unsigned integers. (unsigned integer modulo), - * Reverts with custom message when dividing by zero. - * - * Counterpart to Solidity's `%` operator. This function uses a `revert` - * opcode (which leaves remaining gas untouched) while Solidity uses an - * invalid opcode to revert (consuming all remaining gas). - * - * Requirements: - * - * - The divisor cannot be zero. - */ - function mod( - uint256 a, - uint256 b, - string memory errorMessage - ) internal pure returns (uint256) { - require(b != 0, errorMessage); - return a % b; - } - - // babylonian method (https://en.wikipedia.org/wiki/Methods_of_computing_square_roots#Babylonian_method) - function sqrrt(uint256 a) internal pure returns (uint256 c) { - if (a > 3) { - c = a; - uint256 b = add(div(a, 2), 1); - while (b < c) { - c = b; - b = div(add(div(a, b), b), 2); - } - } else if (a != 0) { - c = 1; - } - } - - /* - * Expects percentage to be trailed by 00, - */ - function percentageAmount(uint256 total_, uint8 percentage_) internal pure returns (uint256 percentAmount_) { - return div(mul(total_, percentage_), 1000); - } - - /* - * Expects percentage to be trailed by 00, - */ - function substractPercentage(uint256 total_, uint8 percentageToSub_) internal pure returns (uint256 result_) { - return sub(total_, div(mul(total_, percentageToSub_), 1000)); - } - - function percentageOfTotal(uint256 part_, uint256 total_) internal pure returns (uint256 percent_) { - return div(mul(part_, 100), total_); - } - - /** - * Taken from Hypersonic https://github.com/M2629/HyperSonic/blob/main/Math.sol - * @dev Returns the average of two numbers. The result is rounded towards - * zero. - */ - function average(uint256 a, uint256 b) internal pure returns (uint256) { - // (a + b) / 2 can overflow, so we distribute - return (a / 2) + (b / 2) + (((a % 2) + (b % 2)) / 2); - } - - function quadraticPricing(uint256 payment_, uint256 multiplier_) internal pure returns (uint256) { - return sqrrt(mul(multiplier_, payment_)); - } - - function bondingCurve(uint256 supply_, uint256 multiplier_) internal pure returns (uint256) { - return mul(multiplier_, supply_); - } -} - -// OpenZeppelin Contracts (last updated v4.7.0) (token/ERC20/utils/SafeERC20.sol) - - - - - -// OpenZeppelin Contracts v4.4.1 (token/ERC20/extensions/draft-IERC20Permit.sol) - - - -/** - * @dev Interface of the ERC20 Permit extension allowing approvals to be made via signatures, as defined in - * https://eips.ethereum.org/EIPS/eip-2612[EIP-2612]. - * - * Adds the {permit} method, which can be used to change an account's ERC20 allowance (see {IERC20-allowance}) by - * presenting a message signed by the account. By not relying on {IERC20-approve}, the token holder account doesn't - * need to send a transaction, and thus is not required to hold Ether at all. - */ -interface IERC20Permit { - /** - * @dev Sets `value` as the allowance of `spender` over ``owner``'s tokens, - * given ``owner``'s signed approval. - * - * IMPORTANT: The same issues {IERC20-approve} has related to transaction - * ordering also apply here. - * - * Emits an {Approval} event. - * - * Requirements: - * - * - `spender` cannot be the zero address. - * - `deadline` must be a timestamp in the future. - * - `v`, `r` and `s` must be a valid `secp256k1` signature from `owner` - * over the EIP712-formatted function arguments. - * - the signature must use ``owner``'s current nonce (see {nonces}). - * - * For more information on the signature format, see the - * https://eips.ethereum.org/EIPS/eip-2612#specification[relevant EIP - * section]. - */ - function permit( - address owner, - address spender, - uint256 value, - uint256 deadline, - uint8 v, - bytes32 r, - bytes32 s - ) external; - - /** - * @dev Returns the current nonce for `owner`. This value must be - * included whenever a signature is generated for {permit}. - * - * Every successful call to {permit} increases ``owner``'s nonce by one. This - * prevents a signature from being used multiple times. - */ - function nonces(address owner) external view returns (uint256); - - /** - * @dev Returns the domain separator used in the encoding of the signature for {permit}, as defined by {EIP712}. - */ - // solhint-disable-next-line func-name-mixedcase - function DOMAIN_SEPARATOR() external view returns (bytes32); -} - - - -/** - * @title SafeERC20 - * @dev Wrappers around ERC20 operations that throw on failure (when the token - * contract returns false). Tokens that return no value (and instead revert or - * throw on failure) are also supported, non-reverting calls are assumed to be - * successful. - * To use this library you can add a `using SafeERC20 for IERC20;` statement to your contract, - * which allows you to call the safe operations as `token.safeTransfer(...)`, etc. - */ -library SafeERC20 { - using Address for address; - - function safeTransfer( - IERC20 token, - address to, - uint256 value - ) internal { - _callOptionalReturn(token, abi.encodeWithSelector(token.transfer.selector, to, value)); - } - - function safeTransferFrom( - IERC20 token, - address from, - address to, - uint256 value - ) internal { - _callOptionalReturn(token, abi.encodeWithSelector(token.transferFrom.selector, from, to, value)); - } - - /** - * @dev Deprecated. This function has issues similar to the ones found in - * {IERC20-approve}, and its usage is discouraged. - * - * Whenever possible, use {safeIncreaseAllowance} and - * {safeDecreaseAllowance} instead. - */ - function safeApprove( - IERC20 token, - address spender, - uint256 value - ) internal { - // safeApprove should only be called when setting an initial allowance, - // or when resetting it to zero. To increase and decrease it, use - // 'safeIncreaseAllowance' and 'safeDecreaseAllowance' - require( - (value == 0) || (token.allowance(address(this), spender) == 0), - "SafeERC20: approve from non-zero to non-zero allowance" - ); - _callOptionalReturn(token, abi.encodeWithSelector(token.approve.selector, spender, value)); - } - - function safeIncreaseAllowance( - IERC20 token, - address spender, - uint256 value - ) internal { - uint256 newAllowance = token.allowance(address(this), spender) + value; - _callOptionalReturn(token, abi.encodeWithSelector(token.approve.selector, spender, newAllowance)); - } - - function safeDecreaseAllowance( - IERC20 token, - address spender, - uint256 value - ) internal { - unchecked { - uint256 oldAllowance = token.allowance(address(this), spender); - require(oldAllowance >= value, "SafeERC20: decreased allowance below zero"); - uint256 newAllowance = oldAllowance - value; - _callOptionalReturn(token, abi.encodeWithSelector(token.approve.selector, spender, newAllowance)); - } - } - - function safePermit( - IERC20Permit token, - address owner, - address spender, - uint256 value, - uint256 deadline, - uint8 v, - bytes32 r, - bytes32 s - ) internal { - uint256 nonceBefore = token.nonces(owner); - token.permit(owner, spender, value, deadline, v, r, s); - uint256 nonceAfter = token.nonces(owner); - require(nonceAfter == nonceBefore + 1, "SafeERC20: permit did not succeed"); - } - - /** - * @dev Imitates a Solidity high-level call (i.e. a regular function call to a contract), relaxing the requirement - * on the return value: the return value is optional (but if data is returned, it must not be false). - * @param token The token targeted by the call. - * @param data The call data (encoded using abi.encode or one of its variants). - */ - function _callOptionalReturn(IERC20 token, bytes memory data) private { - // We need to perform a low level call here, to bypass Solidity's return data size checking mechanism, since - // we're implementing it ourselves. We use {Address.functionCall} to perform this call, which verifies that - // the target address contains contract code and also asserts for success in the low-level call. - - bytes memory returndata = address(token).functionCall(data, "SafeERC20: low-level call failed"); - if (returndata.length > 0) { - // Return data is optional - require(abi.decode(returndata, (bool)), "SafeERC20: ERC20 operation did not succeed"); - } - } -} - - - - - - - - - - - - - - -/** - * @dev Provides information about the current execution context, including the - * sender of the transaction and its data. While these are generally available - * via msg.sender and msg.data, they should not be accessed in such a direct - * manner, since when dealing with meta-transactions the account sending and - * paying for execution may not be the actual sender (as far as an application - * is concerned). - * - * This contract is only required for intermediate, library-like contracts. - */ -abstract contract Context { - function _msgSender() internal view virtual returns (address) { - return msg.sender; - } - - function _msgData() internal view virtual returns (bytes calldata) { - return msg.data; - } -} - - -/** - * @dev Contract module which provides a basic access control mechanism, where - * there is an account (an owner) that can be granted exclusive access to - * specific functions. - * - * By default, the owner account will be the one that deploys the contract. This - * can later be changed with {transferOwnership}. - * - * This module is used through inheritance. It will make available the modifier - * `onlyOwner`, which can be applied to your functions to restrict their use to - * the owner. - */ -abstract contract Ownable is Context { - address private _owner; - - event OwnershipTransferred(address indexed previousOwner, address indexed newOwner); - - /** - * @dev Initializes the contract setting the deployer as the initial owner. - */ - constructor() { - _transferOwnership(_msgSender()); - } - - /** - * @dev Throws if called by any account other than the owner. - */ - modifier onlyOwner() { - _checkOwner(); - _; - } - - /** - * @dev Returns the address of the current owner. - */ - function owner() public view virtual returns (address) { - return _owner; - } - - /** - * @dev Throws if the sender is not the owner. - */ - function _checkOwner() internal view virtual { - require(owner() == _msgSender(), "Ownable: caller is not the owner"); - } - - /** - * @dev Leaves the contract without owner. It will not be possible to call - * `onlyOwner` functions anymore. Can only be called by the current owner. - * - * NOTE: Renouncing ownership will leave the contract without an owner, - * thereby removing any functionality that is only available to the owner. - */ - function renounceOwnership() public virtual onlyOwner { - _transferOwnership(address(0)); - } - - /** - * @dev Transfers ownership of the contract to a new account (`newOwner`). - * Can only be called by the current owner. - */ - function transferOwnership(address newOwner) public virtual onlyOwner { - require(newOwner != address(0), "Ownable: new owner is the zero address"); - _transferOwnership(newOwner); - } - - /** - * @dev Transfers ownership of the contract to a new account (`newOwner`). - * Internal function without access restriction. - */ - function _transferOwnership(address newOwner) internal virtual { - address oldOwner = _owner; - _owner = newOwner; - emit OwnershipTransferred(oldOwner, newOwner); - } -} - - -contract Operator is Ownable { - address public operator; - uint256 constant baseRate = 10000; - - modifier onlyOperator { - require(msg.sender == owner() || msg.sender == operator, "no permission"); - _; - } - - function setOperator(address operator_) external onlyOwner { - operator = operator_; - } - - - function getCurrTime() external view returns(uint256) { - return block.timestamp; - } - - function getBlockNum() external view returns(uint256) { - return block.number; - } - -} - - - - - -/** - * @dev Library for managing - * https://en.wikipedia.org/wiki/Set_(abstract_data_type)[sets] of primitive - * types. - * - * Sets have the following properties: - * - * - Elements are added, removed, and checked for existence in constant time - * (O(1)). - * - Elements are enumerated in O(n). No guarantees are made on the ordering. - * - * ``` - * contract Example { - * // Add the library methods - * using EnumerableSet for EnumerableSet.AddressSet; - * - * // Declare a set state variable - * EnumerableSet.AddressSet private mySet; - * } - * ``` - * - * As of v3.3.0, sets of type `bytes32` (`Bytes32Set`), `address` (`AddressSet`) - * and `uint256` (`UintSet`) are supported. - * - * [WARNING] - * ==== - * Trying to delete such a structure from storage will likely result in data corruption, rendering the structure unusable. - * See https://github.com/ethereum/solidity/pull/11843[ethereum/solidity#11843] for more info. - * - * In order to clean an EnumerableSet, you can either remove all elements one by one or create a fresh instance using an array of EnumerableSet. - * ==== - */ - -library EnumerableSet { - // To implement this library for multiple types with as little code - // repetition as possible, we write it in terms of a generic Set type with - // bytes32 values. - // The Set implementation uses private functions, and user-facing - // implementations (such as AddressSet) are just wrappers around the - // underlying Set. - // This means that we can only create new EnumerableSets for types that fit - // in bytes32. - - struct Set { - // Storage of set values - bytes32[] _values; - // Position of the value in the `values` array, plus 1 because index 0 - // means a value is not in the set. - mapping(bytes32 => uint256) _indexes; - } - - /** - * @dev Add a value to a set. O(1). - * - * Returns true if the value was added to the set, that is if it was not - * already present. - */ - function _add(Set storage set, bytes32 value) private returns (bool) { - if (!_contains(set, value)) { - set._values.push(value); - // The value is stored at length-1, but we add 1 to all indexes - // and use 0 as a sentinel value - set._indexes[value] = set._values.length; - return true; - } else { - return false; - } - } - - /** - * @dev Removes a value from a set. O(1). - * - * Returns true if the value was removed from the set, that is if it was - * present. - */ - function _remove(Set storage set, bytes32 value) private returns (bool) { - // We read and store the value's index to prevent multiple reads from the same storage slot - uint256 valueIndex = set._indexes[value]; - - if (valueIndex != 0) { - // Equivalent to contains(set, value) - // To delete an element from the _values array in O(1), we swap the element to delete with the last one in - // the array, and then remove the last element (sometimes called as 'swap and pop'). - // This modifies the order of the array, as noted in {at}. - - uint256 toDeleteIndex = valueIndex - 1; - uint256 lastIndex = set._values.length - 1; - - if (lastIndex != toDeleteIndex) { - bytes32 lastValue = set._values[lastIndex]; - - // Move the last value to the index where the value to delete is - set._values[toDeleteIndex] = lastValue; - // Update the index for the moved value - set._indexes[lastValue] = valueIndex; // Replace lastValue's index to valueIndex - } - - // Delete the slot where the moved value was stored - set._values.pop(); - - // Delete the index for the deleted slot - delete set._indexes[value]; - - return true; - } else { - return false; - } - } - - /** - * @dev Returns true if the value is in the set. O(1). - */ - function _contains(Set storage set, bytes32 value) private view returns (bool) { - return set._indexes[value] != 0; - } - - /** - * @dev Returns the number of values on the set. O(1). - */ - function _length(Set storage set) private view returns (uint256) { - return set._values.length; - } - - /** - * @dev Returns the value stored at position `index` in the set. O(1). - * - * Note that there are no guarantees on the ordering of values inside the - * array, and it may change when more values are added or removed. - * - * Requirements: - * - * - `index` must be strictly less than {length}. - */ - function _at(Set storage set, uint256 index) private view returns (bytes32) { - return set._values[index]; - } - - /** - * @dev Return the entire set in an array - * - * WARNING: This operation will copy the entire storage to memory, which can be quite expensive. This is designed - * to mostly be used by view accessors that are queried without any gas fees. Developers should keep in mind that - * this function has an unbounded cost, and using it as part of a state-changing function may render the function - * uncallable if the set grows to a point where copying to memory consumes too much gas to fit in a block. - */ - function _values(Set storage set) private view returns (bytes32[] memory) { - return set._values; - } - - // Bytes32Set - - struct Bytes32Set { - Set _inner; - } - - /** - * @dev Add a value to a set. O(1). - * - * Returns true if the value was added to the set, that is if it was not - * already present. - */ - function add(Bytes32Set storage set, bytes32 value) internal returns (bool) { - return _add(set._inner, value); - } - - /** - * @dev Removes a value from a set. O(1). - * - * Returns true if the value was removed from the set, that is if it was - * present. - */ - function remove(Bytes32Set storage set, bytes32 value) internal returns (bool) { - return _remove(set._inner, value); - } - - /** - * @dev Returns true if the value is in the set. O(1). - */ - function contains(Bytes32Set storage set, bytes32 value) internal view returns (bool) { - return _contains(set._inner, value); - } - - /** - * @dev Returns the number of values in the set. O(1). - */ - function length(Bytes32Set storage set) internal view returns (uint256) { - return _length(set._inner); - } - - /** - * @dev Returns the value stored at position `index` in the set. O(1). - * - * Note that there are no guarantees on the ordering of values inside the - * array, and it may change when more values are added or removed. - * - * Requirements: - * - * - `index` must be strictly less than {length}. - */ - function at(Bytes32Set storage set, uint256 index) internal view returns (bytes32) { - return _at(set._inner, index); - } - - /** - * @dev Return the entire set in an array - * - * WARNING: This operation will copy the entire storage to memory, which can be quite expensive. This is designed - * to mostly be used by view accessors that are queried without any gas fees. Developers should keep in mind that - * this function has an unbounded cost, and using it as part of a state-changing function may render the function - * uncallable if the set grows to a point where copying to memory consumes too much gas to fit in a block. - */ - function values(Bytes32Set storage set) internal view returns (bytes32[] memory) { - return _values(set._inner); - } - - // AddressSet - - struct AddressSet { - Set _inner; - } - - /** - * @dev Add a value to a set. O(1). - * - * Returns true if the value was added to the set, that is if it was not - * already present. - */ - function add(AddressSet storage set, address value) internal returns (bool) { - return _add(set._inner, bytes32(uint256(uint160(value)))); - } - - /** - * @dev Removes a value from a set. O(1). - * - * Returns true if the value was removed from the set, that is if it was - * present. - */ - function remove(AddressSet storage set, address value) internal returns (bool) { - return _remove(set._inner, bytes32(uint256(uint160(value)))); - } - - /** - * @dev Returns true if the value is in the set. O(1). - */ - function contains(AddressSet storage set, address value) internal view returns (bool) { - return _contains(set._inner, bytes32(uint256(uint160(value)))); - } - - /** - * @dev Returns the number of values in the set. O(1). - */ - function length(AddressSet storage set) internal view returns (uint256) { - return _length(set._inner); - } - - /** - * @dev Returns the value stored at position `index` in the set. O(1). - * - * Note that there are no guarantees on the ordering of values inside the - * array, and it may change when more values are added or removed. - * - * Requirements: - * - * - `index` must be strictly less than {length}. - */ - function at(AddressSet storage set, uint256 index) internal view returns (address) { - return address(uint160(uint256(_at(set._inner, index)))); - } - - /** - * @dev Return the entire set in an array - * - * WARNING: This operation will copy the entire storage to memory, which can be quite expensive. This is designed - * to mostly be used by view accessors that are queried without any gas fees. Developers should keep in mind that - * this function has an unbounded cost, and using it as part of a state-changing function may render the function - * uncallable if the set grows to a point where copying to memory consumes too much gas to fit in a block. - */ - function values(AddressSet storage set) internal view returns (address[] memory) { - bytes32[] memory store = _values(set._inner); - address[] memory result; - - /// @solidity memory-safe-assembly - assembly { - result := store - } - - return result; - } - - // UintSet - - struct UintSet { - Set _inner; - } - - /** - * @dev Add a value to a set. O(1). - * - * Returns true if the value was added to the set, that is if it was not - * already present. - */ - function add(UintSet storage set, uint256 value) internal returns (bool) { - return _add(set._inner, bytes32(value)); - } - - /** - * @dev Removes a value from a set. O(1). - * - * Returns true if the value was removed from the set, that is if it was - * present. - */ - function remove(UintSet storage set, uint256 value) internal returns (bool) { - return _remove(set._inner, bytes32(value)); - } - - /** - * @dev Returns true if the value is in the set. O(1). - */ - function contains(UintSet storage set, uint256 value) internal view returns (bool) { - return _contains(set._inner, bytes32(value)); - } - - /** - * @dev Returns the number of values on the set. O(1). - */ - function length(UintSet storage set) internal view returns (uint256) { - return _length(set._inner); - } - - /** - * @dev Returns the value stored at position `index` in the set. O(1). - * - * Note that there are no guarantees on the ordering of values inside the - * array, and it may change when more values are added or removed. - * - * Requirements: - * - * - `index` must be strictly less than {length}. - */ - function at(UintSet storage set, uint256 index) internal view returns (uint256) { - return uint256(_at(set._inner, index)); - } - - /** - * @dev Return the entire set in an array - * - * WARNING: This operation will copy the entire storage to memory, which can be quite expensive. This is designed - * to mostly be used by view accessors that are queried without any gas fees. Developers should keep in mind that - * this function has an unbounded cost, and using it as part of a state-changing function may render the function - * uncallable if the set grows to a point where copying to memory consumes too much gas to fit in a block. - */ - function values(UintSet storage set) internal view returns (uint256[] memory) { - bytes32[] memory store = _values(set._inner); - uint256[] memory result; - - /// @solidity memory-safe-assembly - assembly { - result := store - } - - return result; - } -} - - -contract ActivityPool is Operator { - using SafeMath for uint256; - using SafeERC20 for IERC20; - using EnumerableSet for EnumerableSet.AddressSet; - using EnumerableSet for EnumerableSet.UintSet; - - event AddNewAct(uint256 id); - event Bet(address user, uint256 pID, uint256 bType, uint256 amount, uint256 time); - event SetPrize(uint256 pID, uint256 bType); - event Claim(address user, uint256 pID, uint256 bType, uint256 amount); - event RemovePeriodAct(uint256 pID); - - uint256 public constant muti = 1e18; - uint256 public periodID; - uint256 public betID; - - struct UserInfo { - address user; - uint256 pID; - uint256 amount; - uint256 betTime; - uint256 bType; - uint256 claimAmount; - } - - struct ActInfo { - string name; - string aName; - string bName; - address rewardToken; - uint256 startTime; - uint256 endTime; - uint256 minAmount; - uint256 maxAmount; - uint256 aAmount; - uint256 bAmount; - uint256 winType; - bool isBet; - } - - struct TimeInfo { - uint256 time; - uint256 aAmount; - uint256 bAmount; - } - - struct BestInfo { - address aUser; - address bUser; - uint256 aBet; - uint256 bBet; - } - - mapping(uint256 => BestInfo) bestInfo; - mapping(uint256 => uint256) public timeID; - mapping(uint256 => mapping(uint256 => TimeInfo)) public timeInfo; - mapping(address => mapping(uint256 => uint256)) public userBet; - mapping(uint256 => UserInfo) public betInfo; - mapping(uint256 => uint256) public perAmount; - mapping(uint256 => ActInfo) public actInfo; - mapping(uint256 => mapping(uint256 => string)) public descripName; - - mapping(address => EnumerableSet.UintSet) userPid; - mapping(uint256 => EnumerableSet.AddressSet) aUsers; - mapping(uint256 => EnumerableSet.AddressSet) bUsers; - EnumerableSet.UintSet activePeriod; - EnumerableSet.UintSet removePeriod; - - function addNewAct( - string memory name, - string memory aName, - string memory bName, - address token, - uint256 startTime, - uint256 endTime, - uint256 minAmount, - uint256 maxAmount - ) external onlyOperator { - - checkAdd(msg.sender, startTime, endTime, minAmount, maxAmount); - uint256 id = ++periodID; - actInfo[id].name = name; - actInfo[id].aName = aName; - actInfo[id].bName = bName; - actInfo[id].startTime = startTime; - actInfo[id].endTime = endTime; - actInfo[id].minAmount = minAmount; - actInfo[id].maxAmount = maxAmount; - actInfo[id].rewardToken = token; - descripName[id][1] = aName; - descripName[id][2] = bName; - activePeriod.add(id); - - emit AddNewAct(id); - } - - - function removePeriodAct(uint256 pID) external onlyOperator { - checkRemove(pID); - - activePeriod.remove(pID); - removePeriod.add(pID); - - emit RemovePeriodAct(pID); - } - - - function bet(uint256 pID, uint256 bType, uint256 amount) external payable { - checkBet(msg.sender, pID, bType, amount); - if(actInfo[pID].rewardToken == address(0)) { - require(msg.value == amount, "value err"); - } else { - require(msg.value == 0, "value amount err"); - } - - if(bType == 1) { - if(amount > bestInfo[pID].aBet) { - bestInfo[pID].aUser = msg.sender; - bestInfo[pID].aBet = amount; - } - } else { - if(amount > bestInfo[pID].bBet) { - bestInfo[pID].bUser = msg.sender; - bestInfo[pID].bBet = amount; - } - } - - userPid[msg.sender].add(pID); - uint256 id = ++betID; - userBet[msg.sender][pID] = id; - - if(bType == 1) { - aUsers[pID].add(msg.sender); - actInfo[pID].aAmount = actInfo[pID].aAmount.add(amount); - } else { - bUsers[pID].add(msg.sender); - actInfo[pID].bAmount = actInfo[pID].bAmount.add(amount); - } - - actInfo[pID].isBet = true; - betInfo[id].user = msg.sender; - betInfo[id].pID = pID; - betInfo[id].amount = amount; - betInfo[id].betTime = block.timestamp; - betInfo[id].bType = bType; - - uint256 tID = ++timeID[pID]; - timeInfo[pID][tID].time = block.timestamp; - timeInfo[pID][tID].aAmount = actInfo[pID].aAmount; - timeInfo[pID][tID].bAmount = actInfo[pID].bAmount; - - if(actInfo[pID].rewardToken != address(0)) { - IERC20(actInfo[pID].rewardToken).safeTransferFrom(msg.sender, address(this), amount); - } - emit Bet(msg.sender, pID, bType, amount, betInfo[id].betTime); - } - - function setPrize(uint256 pID, uint256 bType) external onlyOperator { - checkSetPrize(msg.sender, pID, bType); - - if(block.timestamp <= actInfo[pID].startTime) { - actInfo[pID].startTime = block.timestamp; - - } - actInfo[pID].endTime = block.timestamp; - - actInfo[pID].winType = bType; - perAmount[pID] = getPerAmount(pID, bType); - - emit SetPrize(pID, bType); - } - - function recive() public payable {} - - function claim(uint256 pID) external { - uint256 amount = checkClaim(msg.sender, pID); - - uint256 id = userBet[msg.sender][pID]; - betInfo[id].claimAmount = amount; - if(actInfo[pID].rewardToken != address(0)) { - IERC20(actInfo[pID].rewardToken).safeTransfer(msg.sender, amount); - } else { - payable(msg.sender).transfer(amount); - } - - emit Claim(msg.sender, pID, betInfo[id].bType, amount); - } - - function checkClaim(address user, uint256 pID) public view returns(uint256 amount) { - require(userPid[user].contains(pID), "not bet"); - uint256 id = userBet[user][pID]; - require(betInfo[id].user == user, "not user"); - require(actInfo[pID].winType != 0, "not prize"); - require(betInfo[id].claimAmount == 0, "has claim"); - - if(actInfo[pID].winType != 3) { - require(actInfo[pID].winType == betInfo[id].bType, "not right"); - amount = perAmount[pID].mul(betInfo[id].amount).div(muti); - require(amount > 0, "no amount"); - } else { - amount = betInfo[id].amount; - } - - return amount; - } - - function getActualRate( - address user, - uint256 pID, - uint256 bType, - uint256 amount - ) external view returns(uint256, uint256, bool) { - if(bType < 1 || bType > 2 || !activePeriod.contains(pID)) { - return (0, 0, false); - } else if(userBet[user][pID] != 0 || actInfo[pID].winType != 0 || amount == 0) { - (uint256 ra, uint256 rb) = getRate(pID, timeID[pID]); - return (ra, rb, false); - } else { - (uint256 aAmount, uint256 bAmount) = (actInfo[pID].aAmount, actInfo[pID].bAmount); - if(bType == 1) { - aAmount = aAmount.add(amount); - } else { - bAmount = bAmount.add(amount); - } - - uint256 total = aAmount.add(bAmount); - if(bAmount == 0 && aAmount != 0) { - return (muti, 0, true); - } - if(bAmount != 0 && aAmount == 0) { - return (0, muti, true); - } - return (total.mul(muti).div(aAmount), total.mul(muti).div(bAmount), true); - } - } - - function getRate(uint256 pID, uint256 tID) public view returns(uint256, uint256) { - (uint256 aAmount, uint256 bAmount) = (timeInfo[pID][tID].aAmount, timeInfo[pID][tID].bAmount); - uint256 total = aAmount.add(bAmount); - if(total == 0) { - return (0, 0); - } - if(bAmount == 0 && aAmount != 0) { - return (muti, 0); - } - if(bAmount != 0 && aAmount == 0) { - return (0, muti); - } - return (total.mul(muti).div(aAmount), total.mul(muti).div(bAmount)); - } - - function getBestInfo(uint256 pID) - external - view - returns(address aUser, address bUser, uint256 aBet, uint256 bBet, uint256 aReward, uint256 bReward) - { - aUser = bestInfo[pID].aUser; - bUser = bestInfo[pID].bUser; - aBet = bestInfo[pID].aBet; - bBet = bestInfo[pID].bBet; - aReward = getPerAmount(pID, 1).mul(aBet).div(muti); - bReward = getPerAmount(pID, 2).mul(bBet).div(muti); - } - - function getPerAmount(uint256 pID, uint256 bType) public view returns(uint256) { - uint256 total = actInfo[pID].aAmount.add(actInfo[pID].bAmount); - if(total == 0) { - return 0; - } - - if(actInfo[pID].winType == 3) { - return muti; - } - - if(bType == 1) { - if(actInfo[pID].aAmount == 0 || actInfo[pID].winType == 2) { - return 0; - } - return total.mul(muti).div(actInfo[pID].aAmount); - } - - if(bType == 2) { - if(actInfo[pID].bAmount == 0 || actInfo[pID].winType == 1) { - return 0; - } - return total.mul(muti).div(actInfo[pID].bAmount); - } - - return 0; - - } - - function checkSetPrize(address user, uint256 pID, uint256 bType) public view returns(bool) { - require(user == owner() || user == operator, "no permission"); - require(bType > 0 && bType <= 3, "type err"); - require(activePeriod.contains(pID), "not active"); - require(actInfo[pID].winType == 0, "has set"); - - return true; - } - - function checkBet( - address user, - uint256 pID, - uint256 bType, - uint256 amount - ) public view returns(bool) { - require(activePeriod.contains(pID), "not active"); - require(actInfo[pID].startTime <= block.timestamp, "not start"); - require(actInfo[pID].endTime > block.timestamp, "has end"); - require(!userPid[user].contains(pID), "has bet"); - require(bType > 0 && bType < 3, "type err"); - require(amount >= actInfo[pID].minAmount && amount <= actInfo[pID].maxAmount, "amount err"); - if(actInfo[pID].rewardToken != address(0)) { - require(IERC20(actInfo[pID].rewardToken).allowance(user, address(this)) >= amount, "not approve enough"); - require(IERC20(actInfo[pID].rewardToken).balanceOf(user) >= amount, "not enough"); - } else { - require(user.balance >= amount, "main token err"); - } - - return true; - } - - - function checkRemove(uint256 pID) public view returns(bool) { - require(activePeriod.contains(pID), "not in"); - require(!actInfo[pID].isBet, "has bet"); - - return true; - } - - function checkAdd( - address user, - uint256 startTime, - uint256 endTime, - uint256 minAmount, - uint256 maxAmount - ) public view returns(bool) { - require(user == owner() || user == operator, "no permission"); - require(startTime > block.timestamp, "startTime err"); - require(endTime > startTime, "endTime err"); - require(minAmount > 0 && maxAmount > minAmount, "amount err"); - - return true; - } - - function getStatus(uint256 pID) external view returns(uint256) { - if(!removePeriod.contains(pID) && !activePeriod.contains(pID)) { - return 5; - } else if(removePeriod.contains(pID)) { - return 6; - } else if(block.timestamp < actInfo[pID].startTime) { - return 1; - } else if ( - actInfo[pID].startTime <= block.timestamp && - actInfo[pID].endTime > block.timestamp - ) { - return 2; - } else if (actInfo[pID].endTime <= block.timestamp && actInfo[pID].winType == 0){ - return 3; - } else if(actInfo[pID].winType != 0) { - return 4; - } - return 0; - } - - function getUserPidNum(address user) external view returns(uint256) { - return userPid[user].length(); - } - - function getUserPid(address user, uint256 index) external view returns(uint256) { - return userPid[user].at(index); - } - - function getAUsersNum(uint256 pID) external view returns(uint256) { - return aUsers[pID].length(); - } - - function getAUsers(uint256 pID, uint256 index) external view returns(address) { - return aUsers[pID].at(index); - } - - function getBUsersNum(uint256 pID) external view returns(uint256) { - return bUsers[pID].length(); - } - - function getBUsers(uint256 pID, uint256 index) external view returns(address) { - return bUsers[pID].at(index); - } - - function getActivePeriodNum() external view returns(uint256) { - return activePeriod.length(); - } - - function getActivePeriod(uint256 index) external view returns(uint256) { - return activePeriod.at(index); - } - - function getRemovePeriodNum() external view returns(uint256) { - return removePeriod.length(); - } - - function getRemovePeriod(uint256 index) external view returns(uint256) { - return removePeriod.at(index); - } -} \ No newline at end of file diff --git a/app/api/uploads/ActivityPool-1729824691606-708783209.sol b/app/api/uploads/ActivityPool-1729824691606-708783209.sol deleted file mode 100644 index daf3372..0000000 --- a/app/api/uploads/ActivityPool-1729824691606-708783209.sol +++ /dev/null @@ -1,1648 +0,0 @@ -// SPDX-License-Identifier: MIT -// OpenZeppelin Contracts (last updated v4.7.0) (utils/Address.sol) - -pragma solidity ^0.8.1; - -/** - * @dev Collection of functions related to the address type - */ -library Address { - /** - * @dev Returns true if `account` is a contract. - * - * [IMPORTANT] - * ==== - * It is unsafe to assume that an address for which this function returns - * false is an externally-owned account (EOA) and not a contract. - * - * Among others, `isContract` will return false for the following - * types of addresses: - * - * - an externally-owned account - * - a contract in construction - * - an address where a contract will be created - * - an address where a contract lived, but was destroyed - * ==== - * - * [IMPORTANT] - * ==== - * You shouldn't rely on `isContract` to protect against flash loan attacks! - * - * Preventing calls from contracts is highly discouraged. It breaks composability, breaks support for smart wallets - * like Gnosis Safe, and does not provide security since it can be circumvented by calling from a contract - * constructor. - * ==== - */ - function isContract(address account) internal view returns (bool) { - // This method relies on extcodesize/address.code.length, which returns 0 - // for contracts in construction, since the code is only stored at the end - // of the constructor execution. - - return account.code.length > 0; - } - - /** - * @dev Replacement for Solidity's `transfer`: sends `amount` wei to - * `recipient`, forwarding all available gas and reverting on errors. - * - * https://eips.ethereum.org/EIPS/eip-1884[EIP1884] increases the gas cost - * of certain opcodes, possibly making contracts go over the 2300 gas limit - * imposed by `transfer`, making them unable to receive funds via - * `transfer`. {sendValue} removes this limitation. - * - * https://diligence.consensys.net/posts/2019/09/stop-using-soliditys-transfer-now/[Learn more]. - * - * IMPORTANT: because control is transferred to `recipient`, care must be - * taken to not create reentrancy vulnerabilities. Consider using - * {ReentrancyGuard} or the - * https://solidity.readthedocs.io/en/v0.5.11/security-considerations.html#use-the-checks-effects-interactions-pattern[checks-effects-interactions pattern]. - */ - function sendValue(address payable recipient, uint256 amount) internal { - require(address(this).balance >= amount, "Address: insufficient balance"); - - (bool success, ) = recipient.call{value: amount}(""); - require(success, "Address: unable to send value, recipient may have reverted"); - } - - /** - * @dev Performs a Solidity function call using a low level `call`. A - * plain `call` is an unsafe replacement for a function call: use this - * function instead. - * - * If `target` reverts with a revert reason, it is bubbled up by this - * function (like regular Solidity function calls). - * - * Returns the raw returned data. To convert to the expected return value, - * use https://solidity.readthedocs.io/en/latest/units-and-global-variables.html?highlight=abi.decode#abi-encoding-and-decoding-functions[`abi.decode`]. - * - * Requirements: - * - * - `target` must be a contract. - * - calling `target` with `data` must not revert. - * - * _Available since v3.1._ - */ - function functionCall(address target, bytes memory data) internal returns (bytes memory) { - return functionCallWithValue(target, data, 0, "Address: low-level call failed"); - } - - /** - * @dev Same as {xref-Address-functionCall-address-bytes-}[`functionCall`], but with - * `errorMessage` as a fallback revert reason when `target` reverts. - * - * _Available since v3.1._ - */ - function functionCall( - address target, - bytes memory data, - string memory errorMessage - ) internal returns (bytes memory) { - return functionCallWithValue(target, data, 0, errorMessage); - } - - /** - * @dev Same as {xref-Address-functionCall-address-bytes-}[`functionCall`], - * but also transferring `value` wei to `target`. - * - * Requirements: - * - * - the calling contract must have an ETH balance of at least `value`. - * - the called Solidity function must be `payable`. - * - * _Available since v3.1._ - */ - function functionCallWithValue( - address target, - bytes memory data, - uint256 value - ) internal returns (bytes memory) { - return functionCallWithValue(target, data, value, "Address: low-level call with value failed"); - } - - /** - * @dev Same as {xref-Address-functionCallWithValue-address-bytes-uint256-}[`functionCallWithValue`], but - * with `errorMessage` as a fallback revert reason when `target` reverts. - * - * _Available since v3.1._ - */ - function functionCallWithValue( - address target, - bytes memory data, - uint256 value, - string memory errorMessage - ) internal returns (bytes memory) { - require(address(this).balance >= value, "Address: insufficient balance for call"); - (bool success, bytes memory returndata) = target.call{value: value}(data); - return verifyCallResultFromTarget(target, success, returndata, errorMessage); - } - - /** - * @dev Same as {xref-Address-functionCall-address-bytes-}[`functionCall`], - * but performing a static call. - * - * _Available since v3.3._ - */ - function functionStaticCall(address target, bytes memory data) internal view returns (bytes memory) { - return functionStaticCall(target, data, "Address: low-level static call failed"); - } - - /** - * @dev Same as {xref-Address-functionCall-address-bytes-string-}[`functionCall`], - * but performing a static call. - * - * _Available since v3.3._ - */ - function functionStaticCall( - address target, - bytes memory data, - string memory errorMessage - ) internal view returns (bytes memory) { - (bool success, bytes memory returndata) = target.staticcall(data); - return verifyCallResultFromTarget(target, success, returndata, errorMessage); - } - - /** - * @dev Same as {xref-Address-functionCall-address-bytes-}[`functionCall`], - * but performing a delegate call. - * - * _Available since v3.4._ - */ - function functionDelegateCall(address target, bytes memory data) internal returns (bytes memory) { - return functionDelegateCall(target, data, "Address: low-level delegate call failed"); - } - - /** - * @dev Same as {xref-Address-functionCall-address-bytes-string-}[`functionCall`], - * but performing a delegate call. - * - * _Available since v3.4._ - */ - function functionDelegateCall( - address target, - bytes memory data, - string memory errorMessage - ) internal returns (bytes memory) { - (bool success, bytes memory returndata) = target.delegatecall(data); - return verifyCallResultFromTarget(target, success, returndata, errorMessage); - } - - /** - * @dev Tool to verify that a low level call to smart-contract was successful, and revert (either by bubbling - * the revert reason or using the provided one) in case of unsuccessful call or if target was not a contract. - * - * _Available since v4.8._ - */ - function verifyCallResultFromTarget( - address target, - bool success, - bytes memory returndata, - string memory errorMessage - ) internal view returns (bytes memory) { - if (success) { - if (returndata.length == 0) { - // only check isContract if the call was successful and the return data is empty - // otherwise we already know that it was a contract - require(isContract(target), "Address: call to non-contract"); - } - return returndata; - } else { - _revert(returndata, errorMessage); - } - } - - /** - * @dev Tool to verify that a low level call was successful, and revert if it wasn't, either by bubbling the - * revert reason or using the provided one. - * - * _Available since v4.3._ - */ - function verifyCallResult( - bool success, - bytes memory returndata, - string memory errorMessage - ) internal pure returns (bytes memory) { - if (success) { - return returndata; - } else { - _revert(returndata, errorMessage); - } - } - - function _revert(bytes memory returndata, string memory errorMessage) private pure { - // Look for revert reason and bubble it up if present - if (returndata.length > 0) { - // The easiest way to bubble the revert reason is using memory via assembly - /// @solidity memory-safe-assembly - assembly { - let returndata_size := mload(returndata) - revert(add(32, returndata), returndata_size) - } - } else { - revert(errorMessage); - } - } -} - -// OpenZeppelin Contracts (last updated v4.6.0) (token/ERC20/IERC20.sol) - - - -/** - * @dev Interface of the ERC20 standard as defined in the EIP. - */ -interface IERC20 { - /** - * @dev Emitted when `value` tokens are moved from one account (`from`) to - * another (`to`). - * - * Note that `value` may be zero. - */ - event Transfer(address indexed from, address indexed to, uint256 value); - - /** - * @dev Emitted when the allowance of a `spender` for an `owner` is set by - * a call to {approve}. `value` is the new allowance. - */ - event Approval(address indexed owner, address indexed spender, uint256 value); - - /** - * @dev Returns the amount of tokens in existence. - */ - function totalSupply() external view returns (uint256); - - /** - * @dev Returns the amount of tokens owned by `account`. - */ - function balanceOf(address account) external view returns (uint256); - - /** - * @dev Moves `amount` tokens from the caller's account to `to`. - * - * Returns a boolean value indicating whether the operation succeeded. - * - * Emits a {Transfer} event. - */ - function transfer(address to, uint256 amount) external returns (bool); - - /** - * @dev Returns the remaining number of tokens that `spender` will be - * allowed to spend on behalf of `owner` through {transferFrom}. This is - * zero by default. - * - * This value changes when {approve} or {transferFrom} are called. - */ - function allowance(address owner, address spender) external view returns (uint256); - - /** - * @dev Sets `amount` as the allowance of `spender` over the caller's tokens. - * - * Returns a boolean value indicating whether the operation succeeded. - * - * IMPORTANT: Beware that changing an allowance with this method brings the risk - * that someone may use both the old and the new allowance by unfortunate - * transaction ordering. One possible solution to mitigate this race - * condition is to first reduce the spender's allowance to 0 and set the - * desired value afterwards: - * https://github.com/ethereum/EIPs/issues/20#issuecomment-263524729 - * - * Emits an {Approval} event. - */ - function approve(address spender, uint256 amount) external returns (bool); - - /** - * @dev Moves `amount` tokens from `from` to `to` using the - * allowance mechanism. `amount` is then deducted from the caller's - * allowance. - * - * Returns a boolean value indicating whether the operation succeeded. - * - * Emits a {Transfer} event. - */ - function transferFrom( - address from, - address to, - uint256 amount - ) external returns (bool); - - - function mint(address account_, uint256 amount_) external; - - function burn(uint256 amount) external; - -} - - - - - - - - - - - -/** - * @dev Wrappers over Solidity's arithmetic operations with added overflow - * checks. - * - * Arithmetic operations in Solidity wrap on overflow. This can easily result - * in bugs, because programmers usually assume that an overflow raises an - * error, which is the standard behavior in high level programming languages. - * `SafeMath` restores this intuition by reverting the transaction when an - * operation overflows. - * - * Using this library instead of the unchecked operations eliminates an entire - * class of bugs, so it's recommended to use it always. - */ -library SafeMath { - /** - * @dev Returns the addition of two unsigned integers, reverting on - * overflow. - * - * Counterpart to Solidity's `+` operator. - * - * Requirements: - * - * - Addition cannot overflow. - */ - function add(uint256 a, uint256 b) internal pure returns (uint256) { - uint256 c = a + b; - require(c >= a, "SafeMath: addition overflow"); - - return c; - } - - /** - * @dev Returns the subtraction of two unsigned integers, reverting on - * overflow (when the result is negative). - * - * Counterpart to Solidity's `-` operator. - * - * Requirements: - * - * - Subtraction cannot overflow. - */ - function sub(uint256 a, uint256 b) internal pure returns (uint256) { - return sub(a, b, "SafeMath: subtraction overflow"); - } - - /** - * @dev Returns the subtraction of two unsigned integers, reverting with custom message on - * overflow (when the result is negative). - * - * Counterpart to Solidity's `-` operator. - * - * Requirements: - * - * - Subtraction cannot overflow. - */ - function sub( - uint256 a, - uint256 b, - string memory errorMessage - ) internal pure returns (uint256) { - require(b <= a, errorMessage); - uint256 c = a - b; - - return c; - } - - /** - * @dev Returns the multiplication of two unsigned integers, reverting on - * overflow. - * - * Counterpart to Solidity's `*` operator. - * - * Requirements: - * - * - Multiplication cannot overflow. - */ - function mul(uint256 a, uint256 b) internal pure returns (uint256) { - // Gas optimization: this is cheaper than requiring 'a' not being zero, but the - // benefit is lost if 'b' is also tested. - // See: https://github.com/OpenZeppelin/openzeppelin-contracts/pull/522 - if (a == 0) { - return 0; - } - - uint256 c = a * b; - require(c / a == b, "SafeMath: multiplication overflow"); - - return c; - } - - /** - * @dev Returns the integer division of two unsigned integers. Reverts on - * division by zero. The result is rounded towards zero. - * - * Counterpart to Solidity's `/` operator. Note: this function uses a - * `revert` opcode (which leaves remaining gas untouched) while Solidity - * uses an invalid opcode to revert (consuming all remaining gas). - * - * Requirements: - * - * - The divisor cannot be zero. - */ - function div(uint256 a, uint256 b) internal pure returns (uint256) { - return div(a, b, "SafeMath: division by zero"); - } - - /** - * @dev Returns the integer division of two unsigned integers. Reverts with custom message on - * division by zero. The result is rounded towards zero. - * - * Counterpart to Solidity's `/` operator. Note: this function uses a - * `revert` opcode (which leaves remaining gas untouched) while Solidity - * uses an invalid opcode to revert (consuming all remaining gas). - * - * Requirements: - * - * - The divisor cannot be zero. - */ - function div( - uint256 a, - uint256 b, - string memory errorMessage - ) internal pure returns (uint256) { - require(b > 0, errorMessage); - uint256 c = a / b; - // assert(a == b * c + a % b); // There is no case in which this doesn't hold - - return c; - } - - /** - * @dev Returns the remainder of dividing two unsigned integers. (unsigned integer modulo), - * Reverts when dividing by zero. - * - * Counterpart to Solidity's `%` operator. This function uses a `revert` - * opcode (which leaves remaining gas untouched) while Solidity uses an - * invalid opcode to revert (consuming all remaining gas). - * - * Requirements: - * - * - The divisor cannot be zero. - */ - function mod(uint256 a, uint256 b) internal pure returns (uint256) { - return mod(a, b, "SafeMath: modulo by zero"); - } - - /** - * @dev Returns the remainder of dividing two unsigned integers. (unsigned integer modulo), - * Reverts with custom message when dividing by zero. - * - * Counterpart to Solidity's `%` operator. This function uses a `revert` - * opcode (which leaves remaining gas untouched) while Solidity uses an - * invalid opcode to revert (consuming all remaining gas). - * - * Requirements: - * - * - The divisor cannot be zero. - */ - function mod( - uint256 a, - uint256 b, - string memory errorMessage - ) internal pure returns (uint256) { - require(b != 0, errorMessage); - return a % b; - } - - // babylonian method (https://en.wikipedia.org/wiki/Methods_of_computing_square_roots#Babylonian_method) - function sqrrt(uint256 a) internal pure returns (uint256 c) { - if (a > 3) { - c = a; - uint256 b = add(div(a, 2), 1); - while (b < c) { - c = b; - b = div(add(div(a, b), b), 2); - } - } else if (a != 0) { - c = 1; - } - } - - /* - * Expects percentage to be trailed by 00, - */ - function percentageAmount(uint256 total_, uint8 percentage_) internal pure returns (uint256 percentAmount_) { - return div(mul(total_, percentage_), 1000); - } - - /* - * Expects percentage to be trailed by 00, - */ - function substractPercentage(uint256 total_, uint8 percentageToSub_) internal pure returns (uint256 result_) { - return sub(total_, div(mul(total_, percentageToSub_), 1000)); - } - - function percentageOfTotal(uint256 part_, uint256 total_) internal pure returns (uint256 percent_) { - return div(mul(part_, 100), total_); - } - - /** - * Taken from Hypersonic https://github.com/M2629/HyperSonic/blob/main/Math.sol - * @dev Returns the average of two numbers. The result is rounded towards - * zero. - */ - function average(uint256 a, uint256 b) internal pure returns (uint256) { - // (a + b) / 2 can overflow, so we distribute - return (a / 2) + (b / 2) + (((a % 2) + (b % 2)) / 2); - } - - function quadraticPricing(uint256 payment_, uint256 multiplier_) internal pure returns (uint256) { - return sqrrt(mul(multiplier_, payment_)); - } - - function bondingCurve(uint256 supply_, uint256 multiplier_) internal pure returns (uint256) { - return mul(multiplier_, supply_); - } -} - -// OpenZeppelin Contracts (last updated v4.7.0) (token/ERC20/utils/SafeERC20.sol) - - - - - -// OpenZeppelin Contracts v4.4.1 (token/ERC20/extensions/draft-IERC20Permit.sol) - - - -/** - * @dev Interface of the ERC20 Permit extension allowing approvals to be made via signatures, as defined in - * https://eips.ethereum.org/EIPS/eip-2612[EIP-2612]. - * - * Adds the {permit} method, which can be used to change an account's ERC20 allowance (see {IERC20-allowance}) by - * presenting a message signed by the account. By not relying on {IERC20-approve}, the token holder account doesn't - * need to send a transaction, and thus is not required to hold Ether at all. - */ -interface IERC20Permit { - /** - * @dev Sets `value` as the allowance of `spender` over ``owner``'s tokens, - * given ``owner``'s signed approval. - * - * IMPORTANT: The same issues {IERC20-approve} has related to transaction - * ordering also apply here. - * - * Emits an {Approval} event. - * - * Requirements: - * - * - `spender` cannot be the zero address. - * - `deadline` must be a timestamp in the future. - * - `v`, `r` and `s` must be a valid `secp256k1` signature from `owner` - * over the EIP712-formatted function arguments. - * - the signature must use ``owner``'s current nonce (see {nonces}). - * - * For more information on the signature format, see the - * https://eips.ethereum.org/EIPS/eip-2612#specification[relevant EIP - * section]. - */ - function permit( - address owner, - address spender, - uint256 value, - uint256 deadline, - uint8 v, - bytes32 r, - bytes32 s - ) external; - - /** - * @dev Returns the current nonce for `owner`. This value must be - * included whenever a signature is generated for {permit}. - * - * Every successful call to {permit} increases ``owner``'s nonce by one. This - * prevents a signature from being used multiple times. - */ - function nonces(address owner) external view returns (uint256); - - /** - * @dev Returns the domain separator used in the encoding of the signature for {permit}, as defined by {EIP712}. - */ - // solhint-disable-next-line func-name-mixedcase - function DOMAIN_SEPARATOR() external view returns (bytes32); -} - - - -/** - * @title SafeERC20 - * @dev Wrappers around ERC20 operations that throw on failure (when the token - * contract returns false). Tokens that return no value (and instead revert or - * throw on failure) are also supported, non-reverting calls are assumed to be - * successful. - * To use this library you can add a `using SafeERC20 for IERC20;` statement to your contract, - * which allows you to call the safe operations as `token.safeTransfer(...)`, etc. - */ -library SafeERC20 { - using Address for address; - - function safeTransfer( - IERC20 token, - address to, - uint256 value - ) internal { - _callOptionalReturn(token, abi.encodeWithSelector(token.transfer.selector, to, value)); - } - - function safeTransferFrom( - IERC20 token, - address from, - address to, - uint256 value - ) internal { - _callOptionalReturn(token, abi.encodeWithSelector(token.transferFrom.selector, from, to, value)); - } - - /** - * @dev Deprecated. This function has issues similar to the ones found in - * {IERC20-approve}, and its usage is discouraged. - * - * Whenever possible, use {safeIncreaseAllowance} and - * {safeDecreaseAllowance} instead. - */ - function safeApprove( - IERC20 token, - address spender, - uint256 value - ) internal { - // safeApprove should only be called when setting an initial allowance, - // or when resetting it to zero. To increase and decrease it, use - // 'safeIncreaseAllowance' and 'safeDecreaseAllowance' - require( - (value == 0) || (token.allowance(address(this), spender) == 0), - "SafeERC20: approve from non-zero to non-zero allowance" - ); - _callOptionalReturn(token, abi.encodeWithSelector(token.approve.selector, spender, value)); - } - - function safeIncreaseAllowance( - IERC20 token, - address spender, - uint256 value - ) internal { - uint256 newAllowance = token.allowance(address(this), spender) + value; - _callOptionalReturn(token, abi.encodeWithSelector(token.approve.selector, spender, newAllowance)); - } - - function safeDecreaseAllowance( - IERC20 token, - address spender, - uint256 value - ) internal { - unchecked { - uint256 oldAllowance = token.allowance(address(this), spender); - require(oldAllowance >= value, "SafeERC20: decreased allowance below zero"); - uint256 newAllowance = oldAllowance - value; - _callOptionalReturn(token, abi.encodeWithSelector(token.approve.selector, spender, newAllowance)); - } - } - - function safePermit( - IERC20Permit token, - address owner, - address spender, - uint256 value, - uint256 deadline, - uint8 v, - bytes32 r, - bytes32 s - ) internal { - uint256 nonceBefore = token.nonces(owner); - token.permit(owner, spender, value, deadline, v, r, s); - uint256 nonceAfter = token.nonces(owner); - require(nonceAfter == nonceBefore + 1, "SafeERC20: permit did not succeed"); - } - - /** - * @dev Imitates a Solidity high-level call (i.e. a regular function call to a contract), relaxing the requirement - * on the return value: the return value is optional (but if data is returned, it must not be false). - * @param token The token targeted by the call. - * @param data The call data (encoded using abi.encode or one of its variants). - */ - function _callOptionalReturn(IERC20 token, bytes memory data) private { - // We need to perform a low level call here, to bypass Solidity's return data size checking mechanism, since - // we're implementing it ourselves. We use {Address.functionCall} to perform this call, which verifies that - // the target address contains contract code and also asserts for success in the low-level call. - - bytes memory returndata = address(token).functionCall(data, "SafeERC20: low-level call failed"); - if (returndata.length > 0) { - // Return data is optional - require(abi.decode(returndata, (bool)), "SafeERC20: ERC20 operation did not succeed"); - } - } -} - - - - - - - - - - - - - - -/** - * @dev Provides information about the current execution context, including the - * sender of the transaction and its data. While these are generally available - * via msg.sender and msg.data, they should not be accessed in such a direct - * manner, since when dealing with meta-transactions the account sending and - * paying for execution may not be the actual sender (as far as an application - * is concerned). - * - * This contract is only required for intermediate, library-like contracts. - */ -abstract contract Context { - function _msgSender() internal view virtual returns (address) { - return msg.sender; - } - - function _msgData() internal view virtual returns (bytes calldata) { - return msg.data; - } -} - - -/** - * @dev Contract module which provides a basic access control mechanism, where - * there is an account (an owner) that can be granted exclusive access to - * specific functions. - * - * By default, the owner account will be the one that deploys the contract. This - * can later be changed with {transferOwnership}. - * - * This module is used through inheritance. It will make available the modifier - * `onlyOwner`, which can be applied to your functions to restrict their use to - * the owner. - */ -abstract contract Ownable is Context { - address private _owner; - - event OwnershipTransferred(address indexed previousOwner, address indexed newOwner); - - /** - * @dev Initializes the contract setting the deployer as the initial owner. - */ - constructor() { - _transferOwnership(_msgSender()); - } - - /** - * @dev Throws if called by any account other than the owner. - */ - modifier onlyOwner() { - _checkOwner(); - _; - } - - /** - * @dev Returns the address of the current owner. - */ - function owner() public view virtual returns (address) { - return _owner; - } - - /** - * @dev Throws if the sender is not the owner. - */ - function _checkOwner() internal view virtual { - require(owner() == _msgSender(), "Ownable: caller is not the owner"); - } - - /** - * @dev Leaves the contract without owner. It will not be possible to call - * `onlyOwner` functions anymore. Can only be called by the current owner. - * - * NOTE: Renouncing ownership will leave the contract without an owner, - * thereby removing any functionality that is only available to the owner. - */ - function renounceOwnership() public virtual onlyOwner { - _transferOwnership(address(0)); - } - - /** - * @dev Transfers ownership of the contract to a new account (`newOwner`). - * Can only be called by the current owner. - */ - function transferOwnership(address newOwner) public virtual onlyOwner { - require(newOwner != address(0), "Ownable: new owner is the zero address"); - _transferOwnership(newOwner); - } - - /** - * @dev Transfers ownership of the contract to a new account (`newOwner`). - * Internal function without access restriction. - */ - function _transferOwnership(address newOwner) internal virtual { - address oldOwner = _owner; - _owner = newOwner; - emit OwnershipTransferred(oldOwner, newOwner); - } -} - - -contract Operator is Ownable { - address public operator; - uint256 constant baseRate = 10000; - - modifier onlyOperator { - require(msg.sender == owner() || msg.sender == operator, "no permission"); - _; - } - - function setOperator(address operator_) external onlyOwner { - operator = operator_; - } - - - function getCurrTime() external view returns(uint256) { - return block.timestamp; - } - - function getBlockNum() external view returns(uint256) { - return block.number; - } - -} - - - - - -/** - * @dev Library for managing - * https://en.wikipedia.org/wiki/Set_(abstract_data_type)[sets] of primitive - * types. - * - * Sets have the following properties: - * - * - Elements are added, removed, and checked for existence in constant time - * (O(1)). - * - Elements are enumerated in O(n). No guarantees are made on the ordering. - * - * ``` - * contract Example { - * // Add the library methods - * using EnumerableSet for EnumerableSet.AddressSet; - * - * // Declare a set state variable - * EnumerableSet.AddressSet private mySet; - * } - * ``` - * - * As of v3.3.0, sets of type `bytes32` (`Bytes32Set`), `address` (`AddressSet`) - * and `uint256` (`UintSet`) are supported. - * - * [WARNING] - * ==== - * Trying to delete such a structure from storage will likely result in data corruption, rendering the structure unusable. - * See https://github.com/ethereum/solidity/pull/11843[ethereum/solidity#11843] for more info. - * - * In order to clean an EnumerableSet, you can either remove all elements one by one or create a fresh instance using an array of EnumerableSet. - * ==== - */ - -library EnumerableSet { - // To implement this library for multiple types with as little code - // repetition as possible, we write it in terms of a generic Set type with - // bytes32 values. - // The Set implementation uses private functions, and user-facing - // implementations (such as AddressSet) are just wrappers around the - // underlying Set. - // This means that we can only create new EnumerableSets for types that fit - // in bytes32. - - struct Set { - // Storage of set values - bytes32[] _values; - // Position of the value in the `values` array, plus 1 because index 0 - // means a value is not in the set. - mapping(bytes32 => uint256) _indexes; - } - - /** - * @dev Add a value to a set. O(1). - * - * Returns true if the value was added to the set, that is if it was not - * already present. - */ - function _add(Set storage set, bytes32 value) private returns (bool) { - if (!_contains(set, value)) { - set._values.push(value); - // The value is stored at length-1, but we add 1 to all indexes - // and use 0 as a sentinel value - set._indexes[value] = set._values.length; - return true; - } else { - return false; - } - } - - /** - * @dev Removes a value from a set. O(1). - * - * Returns true if the value was removed from the set, that is if it was - * present. - */ - function _remove(Set storage set, bytes32 value) private returns (bool) { - // We read and store the value's index to prevent multiple reads from the same storage slot - uint256 valueIndex = set._indexes[value]; - - if (valueIndex != 0) { - // Equivalent to contains(set, value) - // To delete an element from the _values array in O(1), we swap the element to delete with the last one in - // the array, and then remove the last element (sometimes called as 'swap and pop'). - // This modifies the order of the array, as noted in {at}. - - uint256 toDeleteIndex = valueIndex - 1; - uint256 lastIndex = set._values.length - 1; - - if (lastIndex != toDeleteIndex) { - bytes32 lastValue = set._values[lastIndex]; - - // Move the last value to the index where the value to delete is - set._values[toDeleteIndex] = lastValue; - // Update the index for the moved value - set._indexes[lastValue] = valueIndex; // Replace lastValue's index to valueIndex - } - - // Delete the slot where the moved value was stored - set._values.pop(); - - // Delete the index for the deleted slot - delete set._indexes[value]; - - return true; - } else { - return false; - } - } - - /** - * @dev Returns true if the value is in the set. O(1). - */ - function _contains(Set storage set, bytes32 value) private view returns (bool) { - return set._indexes[value] != 0; - } - - /** - * @dev Returns the number of values on the set. O(1). - */ - function _length(Set storage set) private view returns (uint256) { - return set._values.length; - } - - /** - * @dev Returns the value stored at position `index` in the set. O(1). - * - * Note that there are no guarantees on the ordering of values inside the - * array, and it may change when more values are added or removed. - * - * Requirements: - * - * - `index` must be strictly less than {length}. - */ - function _at(Set storage set, uint256 index) private view returns (bytes32) { - return set._values[index]; - } - - /** - * @dev Return the entire set in an array - * - * WARNING: This operation will copy the entire storage to memory, which can be quite expensive. This is designed - * to mostly be used by view accessors that are queried without any gas fees. Developers should keep in mind that - * this function has an unbounded cost, and using it as part of a state-changing function may render the function - * uncallable if the set grows to a point where copying to memory consumes too much gas to fit in a block. - */ - function _values(Set storage set) private view returns (bytes32[] memory) { - return set._values; - } - - // Bytes32Set - - struct Bytes32Set { - Set _inner; - } - - /** - * @dev Add a value to a set. O(1). - * - * Returns true if the value was added to the set, that is if it was not - * already present. - */ - function add(Bytes32Set storage set, bytes32 value) internal returns (bool) { - return _add(set._inner, value); - } - - /** - * @dev Removes a value from a set. O(1). - * - * Returns true if the value was removed from the set, that is if it was - * present. - */ - function remove(Bytes32Set storage set, bytes32 value) internal returns (bool) { - return _remove(set._inner, value); - } - - /** - * @dev Returns true if the value is in the set. O(1). - */ - function contains(Bytes32Set storage set, bytes32 value) internal view returns (bool) { - return _contains(set._inner, value); - } - - /** - * @dev Returns the number of values in the set. O(1). - */ - function length(Bytes32Set storage set) internal view returns (uint256) { - return _length(set._inner); - } - - /** - * @dev Returns the value stored at position `index` in the set. O(1). - * - * Note that there are no guarantees on the ordering of values inside the - * array, and it may change when more values are added or removed. - * - * Requirements: - * - * - `index` must be strictly less than {length}. - */ - function at(Bytes32Set storage set, uint256 index) internal view returns (bytes32) { - return _at(set._inner, index); - } - - /** - * @dev Return the entire set in an array - * - * WARNING: This operation will copy the entire storage to memory, which can be quite expensive. This is designed - * to mostly be used by view accessors that are queried without any gas fees. Developers should keep in mind that - * this function has an unbounded cost, and using it as part of a state-changing function may render the function - * uncallable if the set grows to a point where copying to memory consumes too much gas to fit in a block. - */ - function values(Bytes32Set storage set) internal view returns (bytes32[] memory) { - return _values(set._inner); - } - - // AddressSet - - struct AddressSet { - Set _inner; - } - - /** - * @dev Add a value to a set. O(1). - * - * Returns true if the value was added to the set, that is if it was not - * already present. - */ - function add(AddressSet storage set, address value) internal returns (bool) { - return _add(set._inner, bytes32(uint256(uint160(value)))); - } - - /** - * @dev Removes a value from a set. O(1). - * - * Returns true if the value was removed from the set, that is if it was - * present. - */ - function remove(AddressSet storage set, address value) internal returns (bool) { - return _remove(set._inner, bytes32(uint256(uint160(value)))); - } - - /** - * @dev Returns true if the value is in the set. O(1). - */ - function contains(AddressSet storage set, address value) internal view returns (bool) { - return _contains(set._inner, bytes32(uint256(uint160(value)))); - } - - /** - * @dev Returns the number of values in the set. O(1). - */ - function length(AddressSet storage set) internal view returns (uint256) { - return _length(set._inner); - } - - /** - * @dev Returns the value stored at position `index` in the set. O(1). - * - * Note that there are no guarantees on the ordering of values inside the - * array, and it may change when more values are added or removed. - * - * Requirements: - * - * - `index` must be strictly less than {length}. - */ - function at(AddressSet storage set, uint256 index) internal view returns (address) { - return address(uint160(uint256(_at(set._inner, index)))); - } - - /** - * @dev Return the entire set in an array - * - * WARNING: This operation will copy the entire storage to memory, which can be quite expensive. This is designed - * to mostly be used by view accessors that are queried without any gas fees. Developers should keep in mind that - * this function has an unbounded cost, and using it as part of a state-changing function may render the function - * uncallable if the set grows to a point where copying to memory consumes too much gas to fit in a block. - */ - function values(AddressSet storage set) internal view returns (address[] memory) { - bytes32[] memory store = _values(set._inner); - address[] memory result; - - /// @solidity memory-safe-assembly - assembly { - result := store - } - - return result; - } - - // UintSet - - struct UintSet { - Set _inner; - } - - /** - * @dev Add a value to a set. O(1). - * - * Returns true if the value was added to the set, that is if it was not - * already present. - */ - function add(UintSet storage set, uint256 value) internal returns (bool) { - return _add(set._inner, bytes32(value)); - } - - /** - * @dev Removes a value from a set. O(1). - * - * Returns true if the value was removed from the set, that is if it was - * present. - */ - function remove(UintSet storage set, uint256 value) internal returns (bool) { - return _remove(set._inner, bytes32(value)); - } - - /** - * @dev Returns true if the value is in the set. O(1). - */ - function contains(UintSet storage set, uint256 value) internal view returns (bool) { - return _contains(set._inner, bytes32(value)); - } - - /** - * @dev Returns the number of values on the set. O(1). - */ - function length(UintSet storage set) internal view returns (uint256) { - return _length(set._inner); - } - - /** - * @dev Returns the value stored at position `index` in the set. O(1). - * - * Note that there are no guarantees on the ordering of values inside the - * array, and it may change when more values are added or removed. - * - * Requirements: - * - * - `index` must be strictly less than {length}. - */ - function at(UintSet storage set, uint256 index) internal view returns (uint256) { - return uint256(_at(set._inner, index)); - } - - /** - * @dev Return the entire set in an array - * - * WARNING: This operation will copy the entire storage to memory, which can be quite expensive. This is designed - * to mostly be used by view accessors that are queried without any gas fees. Developers should keep in mind that - * this function has an unbounded cost, and using it as part of a state-changing function may render the function - * uncallable if the set grows to a point where copying to memory consumes too much gas to fit in a block. - */ - function values(UintSet storage set) internal view returns (uint256[] memory) { - bytes32[] memory store = _values(set._inner); - uint256[] memory result; - - /// @solidity memory-safe-assembly - assembly { - result := store - } - - return result; - } -} - - -contract ActivityPool is Operator { - using SafeMath for uint256; - using SafeERC20 for IERC20; - using EnumerableSet for EnumerableSet.AddressSet; - using EnumerableSet for EnumerableSet.UintSet; - - event AddNewAct(uint256 id); - event Bet(address user, uint256 pID, uint256 bType, uint256 amount, uint256 time); - event SetPrize(uint256 pID, uint256 bType); - event Claim(address user, uint256 pID, uint256 bType, uint256 amount); - event RemovePeriodAct(uint256 pID); - - uint256 public constant muti = 1e18; - uint256 public periodID; - uint256 public betID; - - struct UserInfo { - address user; - uint256 pID; - uint256 amount; - uint256 betTime; - uint256 bType; - uint256 claimAmount; - } - - struct ActInfo { - string name; - string aName; - string bName; - address rewardToken; - uint256 startTime; - uint256 endTime; - uint256 minAmount; - uint256 maxAmount; - uint256 aAmount; - uint256 bAmount; - uint256 winType; - bool isBet; - } - - struct TimeInfo { - uint256 time; - uint256 aAmount; - uint256 bAmount; - } - - struct BestInfo { - address aUser; - address bUser; - uint256 aBet; - uint256 bBet; - } - - mapping(uint256 => BestInfo) bestInfo; - mapping(uint256 => uint256) public timeID; - mapping(uint256 => mapping(uint256 => TimeInfo)) public timeInfo; - mapping(address => mapping(uint256 => uint256)) public userBet; - mapping(uint256 => UserInfo) public betInfo; - mapping(uint256 => uint256) public perAmount; - mapping(uint256 => ActInfo) public actInfo; - mapping(uint256 => mapping(uint256 => string)) public descripName; - - mapping(address => EnumerableSet.UintSet) userPid; - mapping(uint256 => EnumerableSet.AddressSet) aUsers; - mapping(uint256 => EnumerableSet.AddressSet) bUsers; - EnumerableSet.UintSet activePeriod; - EnumerableSet.UintSet removePeriod; - - function addNewAct( - string memory name, - string memory aName, - string memory bName, - address token, - uint256 startTime, - uint256 endTime, - uint256 minAmount, - uint256 maxAmount - ) external onlyOperator { - - checkAdd(msg.sender, startTime, endTime, minAmount, maxAmount); - uint256 id = ++periodID; - actInfo[id].name = name; - actInfo[id].aName = aName; - actInfo[id].bName = bName; - actInfo[id].startTime = startTime; - actInfo[id].endTime = endTime; - actInfo[id].minAmount = minAmount; - actInfo[id].maxAmount = maxAmount; - actInfo[id].rewardToken = token; - descripName[id][1] = aName; - descripName[id][2] = bName; - activePeriod.add(id); - - emit AddNewAct(id); - } - - - function removePeriodAct(uint256 pID) external onlyOperator { - checkRemove(pID); - - activePeriod.remove(pID); - removePeriod.add(pID); - - emit RemovePeriodAct(pID); - } - - - function bet(uint256 pID, uint256 bType, uint256 amount) external payable { - checkBet(msg.sender, pID, bType, amount); - if(actInfo[pID].rewardToken == address(0)) { - require(msg.value == amount, "value err"); - } else { - require(msg.value == 0, "value amount err"); - } - - if(bType == 1) { - if(amount > bestInfo[pID].aBet) { - bestInfo[pID].aUser = msg.sender; - bestInfo[pID].aBet = amount; - } - } else { - if(amount > bestInfo[pID].bBet) { - bestInfo[pID].bUser = msg.sender; - bestInfo[pID].bBet = amount; - } - } - - userPid[msg.sender].add(pID); - uint256 id = ++betID; - userBet[msg.sender][pID] = id; - - if(bType == 1) { - aUsers[pID].add(msg.sender); - actInfo[pID].aAmount = actInfo[pID].aAmount.add(amount); - } else { - bUsers[pID].add(msg.sender); - actInfo[pID].bAmount = actInfo[pID].bAmount.add(amount); - } - - actInfo[pID].isBet = true; - betInfo[id].user = msg.sender; - betInfo[id].pID = pID; - betInfo[id].amount = amount; - betInfo[id].betTime = block.timestamp; - betInfo[id].bType = bType; - - uint256 tID = ++timeID[pID]; - timeInfo[pID][tID].time = block.timestamp; - timeInfo[pID][tID].aAmount = actInfo[pID].aAmount; - timeInfo[pID][tID].bAmount = actInfo[pID].bAmount; - - if(actInfo[pID].rewardToken != address(0)) { - IERC20(actInfo[pID].rewardToken).safeTransferFrom(msg.sender, address(this), amount); - } - emit Bet(msg.sender, pID, bType, amount, betInfo[id].betTime); - } - - function setPrize(uint256 pID, uint256 bType) external onlyOperator { - checkSetPrize(msg.sender, pID, bType); - - if(block.timestamp <= actInfo[pID].startTime) { - actInfo[pID].startTime = block.timestamp; - - } - actInfo[pID].endTime = block.timestamp; - - actInfo[pID].winType = bType; - perAmount[pID] = getPerAmount(pID, bType); - - emit SetPrize(pID, bType); - } - - function recive() public payable {} - - function claim(uint256 pID) external { - uint256 amount = checkClaim(msg.sender, pID); - - uint256 id = userBet[msg.sender][pID]; - betInfo[id].claimAmount = amount; - if(actInfo[pID].rewardToken != address(0)) { - IERC20(actInfo[pID].rewardToken).safeTransfer(msg.sender, amount); - } else { - payable(msg.sender).transfer(amount); - } - - emit Claim(msg.sender, pID, betInfo[id].bType, amount); - } - - function checkClaim(address user, uint256 pID) public view returns(uint256 amount) { - require(userPid[user].contains(pID), "not bet"); - uint256 id = userBet[user][pID]; - require(betInfo[id].user == user, "not user"); - require(actInfo[pID].winType != 0, "not prize"); - require(betInfo[id].claimAmount == 0, "has claim"); - - if(actInfo[pID].winType != 3) { - require(actInfo[pID].winType == betInfo[id].bType, "not right"); - amount = perAmount[pID].mul(betInfo[id].amount).div(muti); - require(amount > 0, "no amount"); - } else { - amount = betInfo[id].amount; - } - - return amount; - } - - function getActualRate( - address user, - uint256 pID, - uint256 bType, - uint256 amount - ) external view returns(uint256, uint256, bool) { - if(bType < 1 || bType > 2 || !activePeriod.contains(pID)) { - return (0, 0, false); - } else if(userBet[user][pID] != 0 || actInfo[pID].winType != 0 || amount == 0) { - (uint256 ra, uint256 rb) = getRate(pID, timeID[pID]); - return (ra, rb, false); - } else { - (uint256 aAmount, uint256 bAmount) = (actInfo[pID].aAmount, actInfo[pID].bAmount); - if(bType == 1) { - aAmount = aAmount.add(amount); - } else { - bAmount = bAmount.add(amount); - } - - uint256 total = aAmount.add(bAmount); - if(bAmount == 0 && aAmount != 0) { - return (muti, 0, true); - } - if(bAmount != 0 && aAmount == 0) { - return (0, muti, true); - } - return (total.mul(muti).div(aAmount), total.mul(muti).div(bAmount), true); - } - } - - function getRate(uint256 pID, uint256 tID) public view returns(uint256, uint256) { - (uint256 aAmount, uint256 bAmount) = (timeInfo[pID][tID].aAmount, timeInfo[pID][tID].bAmount); - uint256 total = aAmount.add(bAmount); - if(total == 0) { - return (0, 0); - } - if(bAmount == 0 && aAmount != 0) { - return (muti, 0); - } - if(bAmount != 0 && aAmount == 0) { - return (0, muti); - } - return (total.mul(muti).div(aAmount), total.mul(muti).div(bAmount)); - } - - function getBestInfo(uint256 pID) - external - view - returns(address aUser, address bUser, uint256 aBet, uint256 bBet, uint256 aReward, uint256 bReward) - { - aUser = bestInfo[pID].aUser; - bUser = bestInfo[pID].bUser; - aBet = bestInfo[pID].aBet; - bBet = bestInfo[pID].bBet; - aReward = getPerAmount(pID, 1).mul(aBet).div(muti); - bReward = getPerAmount(pID, 2).mul(bBet).div(muti); - } - - function getPerAmount(uint256 pID, uint256 bType) public view returns(uint256) { - uint256 total = actInfo[pID].aAmount.add(actInfo[pID].bAmount); - if(total == 0) { - return 0; - } - - if(actInfo[pID].winType == 3) { - return muti; - } - - if(bType == 1) { - if(actInfo[pID].aAmount == 0 || actInfo[pID].winType == 2) { - return 0; - } - return total.mul(muti).div(actInfo[pID].aAmount); - } - - if(bType == 2) { - if(actInfo[pID].bAmount == 0 || actInfo[pID].winType == 1) { - return 0; - } - return total.mul(muti).div(actInfo[pID].bAmount); - } - - return 0; - - } - - function checkSetPrize(address user, uint256 pID, uint256 bType) public view returns(bool) { - require(user == owner() || user == operator, "no permission"); - require(bType > 0 && bType <= 3, "type err"); - require(activePeriod.contains(pID), "not active"); - require(actInfo[pID].winType == 0, "has set"); - - return true; - } - - function checkBet( - address user, - uint256 pID, - uint256 bType, - uint256 amount - ) public view returns(bool) { - require(activePeriod.contains(pID), "not active"); - require(actInfo[pID].startTime <= block.timestamp, "not start"); - require(actInfo[pID].endTime > block.timestamp, "has end"); - require(!userPid[user].contains(pID), "has bet"); - require(bType > 0 && bType < 3, "type err"); - require(amount >= actInfo[pID].minAmount && amount <= actInfo[pID].maxAmount, "amount err"); - if(actInfo[pID].rewardToken != address(0)) { - require(IERC20(actInfo[pID].rewardToken).allowance(user, address(this)) >= amount, "not approve enough"); - require(IERC20(actInfo[pID].rewardToken).balanceOf(user) >= amount, "not enough"); - } else { - require(user.balance >= amount, "main token err"); - } - - return true; - } - - - function checkRemove(uint256 pID) public view returns(bool) { - require(activePeriod.contains(pID), "not in"); - require(!actInfo[pID].isBet, "has bet"); - - return true; - } - - function checkAdd( - address user, - uint256 startTime, - uint256 endTime, - uint256 minAmount, - uint256 maxAmount - ) public view returns(bool) { - require(user == owner() || user == operator, "no permission"); - require(startTime > block.timestamp, "startTime err"); - require(endTime > startTime, "endTime err"); - require(minAmount > 0 && maxAmount > minAmount, "amount err"); - - return true; - } - - function getStatus(uint256 pID) external view returns(uint256) { - if(!removePeriod.contains(pID) && !activePeriod.contains(pID)) { - return 5; - } else if(removePeriod.contains(pID)) { - return 6; - } else if(block.timestamp < actInfo[pID].startTime) { - return 1; - } else if ( - actInfo[pID].startTime <= block.timestamp && - actInfo[pID].endTime > block.timestamp - ) { - return 2; - } else if (actInfo[pID].endTime <= block.timestamp && actInfo[pID].winType == 0){ - return 3; - } else if(actInfo[pID].winType != 0) { - return 4; - } - return 0; - } - - function getUserPidNum(address user) external view returns(uint256) { - return userPid[user].length(); - } - - function getUserPid(address user, uint256 index) external view returns(uint256) { - return userPid[user].at(index); - } - - function getAUsersNum(uint256 pID) external view returns(uint256) { - return aUsers[pID].length(); - } - - function getAUsers(uint256 pID, uint256 index) external view returns(address) { - return aUsers[pID].at(index); - } - - function getBUsersNum(uint256 pID) external view returns(uint256) { - return bUsers[pID].length(); - } - - function getBUsers(uint256 pID, uint256 index) external view returns(address) { - return bUsers[pID].at(index); - } - - function getActivePeriodNum() external view returns(uint256) { - return activePeriod.length(); - } - - function getActivePeriod(uint256 index) external view returns(uint256) { - return activePeriod.at(index); - } - - function getRemovePeriodNum() external view returns(uint256) { - return removePeriod.length(); - } - - function getRemovePeriod(uint256 index) external view returns(uint256) { - return removePeriod.at(index); - } -} \ No newline at end of file diff --git a/app/api/uploads/ActivityPool-1729824763048-505946666.sol b/app/api/uploads/ActivityPool-1729824763048-505946666.sol deleted file mode 100644 index daf3372..0000000 --- a/app/api/uploads/ActivityPool-1729824763048-505946666.sol +++ /dev/null @@ -1,1648 +0,0 @@ -// SPDX-License-Identifier: MIT -// OpenZeppelin Contracts (last updated v4.7.0) (utils/Address.sol) - -pragma solidity ^0.8.1; - -/** - * @dev Collection of functions related to the address type - */ -library Address { - /** - * @dev Returns true if `account` is a contract. - * - * [IMPORTANT] - * ==== - * It is unsafe to assume that an address for which this function returns - * false is an externally-owned account (EOA) and not a contract. - * - * Among others, `isContract` will return false for the following - * types of addresses: - * - * - an externally-owned account - * - a contract in construction - * - an address where a contract will be created - * - an address where a contract lived, but was destroyed - * ==== - * - * [IMPORTANT] - * ==== - * You shouldn't rely on `isContract` to protect against flash loan attacks! - * - * Preventing calls from contracts is highly discouraged. It breaks composability, breaks support for smart wallets - * like Gnosis Safe, and does not provide security since it can be circumvented by calling from a contract - * constructor. - * ==== - */ - function isContract(address account) internal view returns (bool) { - // This method relies on extcodesize/address.code.length, which returns 0 - // for contracts in construction, since the code is only stored at the end - // of the constructor execution. - - return account.code.length > 0; - } - - /** - * @dev Replacement for Solidity's `transfer`: sends `amount` wei to - * `recipient`, forwarding all available gas and reverting on errors. - * - * https://eips.ethereum.org/EIPS/eip-1884[EIP1884] increases the gas cost - * of certain opcodes, possibly making contracts go over the 2300 gas limit - * imposed by `transfer`, making them unable to receive funds via - * `transfer`. {sendValue} removes this limitation. - * - * https://diligence.consensys.net/posts/2019/09/stop-using-soliditys-transfer-now/[Learn more]. - * - * IMPORTANT: because control is transferred to `recipient`, care must be - * taken to not create reentrancy vulnerabilities. Consider using - * {ReentrancyGuard} or the - * https://solidity.readthedocs.io/en/v0.5.11/security-considerations.html#use-the-checks-effects-interactions-pattern[checks-effects-interactions pattern]. - */ - function sendValue(address payable recipient, uint256 amount) internal { - require(address(this).balance >= amount, "Address: insufficient balance"); - - (bool success, ) = recipient.call{value: amount}(""); - require(success, "Address: unable to send value, recipient may have reverted"); - } - - /** - * @dev Performs a Solidity function call using a low level `call`. A - * plain `call` is an unsafe replacement for a function call: use this - * function instead. - * - * If `target` reverts with a revert reason, it is bubbled up by this - * function (like regular Solidity function calls). - * - * Returns the raw returned data. To convert to the expected return value, - * use https://solidity.readthedocs.io/en/latest/units-and-global-variables.html?highlight=abi.decode#abi-encoding-and-decoding-functions[`abi.decode`]. - * - * Requirements: - * - * - `target` must be a contract. - * - calling `target` with `data` must not revert. - * - * _Available since v3.1._ - */ - function functionCall(address target, bytes memory data) internal returns (bytes memory) { - return functionCallWithValue(target, data, 0, "Address: low-level call failed"); - } - - /** - * @dev Same as {xref-Address-functionCall-address-bytes-}[`functionCall`], but with - * `errorMessage` as a fallback revert reason when `target` reverts. - * - * _Available since v3.1._ - */ - function functionCall( - address target, - bytes memory data, - string memory errorMessage - ) internal returns (bytes memory) { - return functionCallWithValue(target, data, 0, errorMessage); - } - - /** - * @dev Same as {xref-Address-functionCall-address-bytes-}[`functionCall`], - * but also transferring `value` wei to `target`. - * - * Requirements: - * - * - the calling contract must have an ETH balance of at least `value`. - * - the called Solidity function must be `payable`. - * - * _Available since v3.1._ - */ - function functionCallWithValue( - address target, - bytes memory data, - uint256 value - ) internal returns (bytes memory) { - return functionCallWithValue(target, data, value, "Address: low-level call with value failed"); - } - - /** - * @dev Same as {xref-Address-functionCallWithValue-address-bytes-uint256-}[`functionCallWithValue`], but - * with `errorMessage` as a fallback revert reason when `target` reverts. - * - * _Available since v3.1._ - */ - function functionCallWithValue( - address target, - bytes memory data, - uint256 value, - string memory errorMessage - ) internal returns (bytes memory) { - require(address(this).balance >= value, "Address: insufficient balance for call"); - (bool success, bytes memory returndata) = target.call{value: value}(data); - return verifyCallResultFromTarget(target, success, returndata, errorMessage); - } - - /** - * @dev Same as {xref-Address-functionCall-address-bytes-}[`functionCall`], - * but performing a static call. - * - * _Available since v3.3._ - */ - function functionStaticCall(address target, bytes memory data) internal view returns (bytes memory) { - return functionStaticCall(target, data, "Address: low-level static call failed"); - } - - /** - * @dev Same as {xref-Address-functionCall-address-bytes-string-}[`functionCall`], - * but performing a static call. - * - * _Available since v3.3._ - */ - function functionStaticCall( - address target, - bytes memory data, - string memory errorMessage - ) internal view returns (bytes memory) { - (bool success, bytes memory returndata) = target.staticcall(data); - return verifyCallResultFromTarget(target, success, returndata, errorMessage); - } - - /** - * @dev Same as {xref-Address-functionCall-address-bytes-}[`functionCall`], - * but performing a delegate call. - * - * _Available since v3.4._ - */ - function functionDelegateCall(address target, bytes memory data) internal returns (bytes memory) { - return functionDelegateCall(target, data, "Address: low-level delegate call failed"); - } - - /** - * @dev Same as {xref-Address-functionCall-address-bytes-string-}[`functionCall`], - * but performing a delegate call. - * - * _Available since v3.4._ - */ - function functionDelegateCall( - address target, - bytes memory data, - string memory errorMessage - ) internal returns (bytes memory) { - (bool success, bytes memory returndata) = target.delegatecall(data); - return verifyCallResultFromTarget(target, success, returndata, errorMessage); - } - - /** - * @dev Tool to verify that a low level call to smart-contract was successful, and revert (either by bubbling - * the revert reason or using the provided one) in case of unsuccessful call or if target was not a contract. - * - * _Available since v4.8._ - */ - function verifyCallResultFromTarget( - address target, - bool success, - bytes memory returndata, - string memory errorMessage - ) internal view returns (bytes memory) { - if (success) { - if (returndata.length == 0) { - // only check isContract if the call was successful and the return data is empty - // otherwise we already know that it was a contract - require(isContract(target), "Address: call to non-contract"); - } - return returndata; - } else { - _revert(returndata, errorMessage); - } - } - - /** - * @dev Tool to verify that a low level call was successful, and revert if it wasn't, either by bubbling the - * revert reason or using the provided one. - * - * _Available since v4.3._ - */ - function verifyCallResult( - bool success, - bytes memory returndata, - string memory errorMessage - ) internal pure returns (bytes memory) { - if (success) { - return returndata; - } else { - _revert(returndata, errorMessage); - } - } - - function _revert(bytes memory returndata, string memory errorMessage) private pure { - // Look for revert reason and bubble it up if present - if (returndata.length > 0) { - // The easiest way to bubble the revert reason is using memory via assembly - /// @solidity memory-safe-assembly - assembly { - let returndata_size := mload(returndata) - revert(add(32, returndata), returndata_size) - } - } else { - revert(errorMessage); - } - } -} - -// OpenZeppelin Contracts (last updated v4.6.0) (token/ERC20/IERC20.sol) - - - -/** - * @dev Interface of the ERC20 standard as defined in the EIP. - */ -interface IERC20 { - /** - * @dev Emitted when `value` tokens are moved from one account (`from`) to - * another (`to`). - * - * Note that `value` may be zero. - */ - event Transfer(address indexed from, address indexed to, uint256 value); - - /** - * @dev Emitted when the allowance of a `spender` for an `owner` is set by - * a call to {approve}. `value` is the new allowance. - */ - event Approval(address indexed owner, address indexed spender, uint256 value); - - /** - * @dev Returns the amount of tokens in existence. - */ - function totalSupply() external view returns (uint256); - - /** - * @dev Returns the amount of tokens owned by `account`. - */ - function balanceOf(address account) external view returns (uint256); - - /** - * @dev Moves `amount` tokens from the caller's account to `to`. - * - * Returns a boolean value indicating whether the operation succeeded. - * - * Emits a {Transfer} event. - */ - function transfer(address to, uint256 amount) external returns (bool); - - /** - * @dev Returns the remaining number of tokens that `spender` will be - * allowed to spend on behalf of `owner` through {transferFrom}. This is - * zero by default. - * - * This value changes when {approve} or {transferFrom} are called. - */ - function allowance(address owner, address spender) external view returns (uint256); - - /** - * @dev Sets `amount` as the allowance of `spender` over the caller's tokens. - * - * Returns a boolean value indicating whether the operation succeeded. - * - * IMPORTANT: Beware that changing an allowance with this method brings the risk - * that someone may use both the old and the new allowance by unfortunate - * transaction ordering. One possible solution to mitigate this race - * condition is to first reduce the spender's allowance to 0 and set the - * desired value afterwards: - * https://github.com/ethereum/EIPs/issues/20#issuecomment-263524729 - * - * Emits an {Approval} event. - */ - function approve(address spender, uint256 amount) external returns (bool); - - /** - * @dev Moves `amount` tokens from `from` to `to` using the - * allowance mechanism. `amount` is then deducted from the caller's - * allowance. - * - * Returns a boolean value indicating whether the operation succeeded. - * - * Emits a {Transfer} event. - */ - function transferFrom( - address from, - address to, - uint256 amount - ) external returns (bool); - - - function mint(address account_, uint256 amount_) external; - - function burn(uint256 amount) external; - -} - - - - - - - - - - - -/** - * @dev Wrappers over Solidity's arithmetic operations with added overflow - * checks. - * - * Arithmetic operations in Solidity wrap on overflow. This can easily result - * in bugs, because programmers usually assume that an overflow raises an - * error, which is the standard behavior in high level programming languages. - * `SafeMath` restores this intuition by reverting the transaction when an - * operation overflows. - * - * Using this library instead of the unchecked operations eliminates an entire - * class of bugs, so it's recommended to use it always. - */ -library SafeMath { - /** - * @dev Returns the addition of two unsigned integers, reverting on - * overflow. - * - * Counterpart to Solidity's `+` operator. - * - * Requirements: - * - * - Addition cannot overflow. - */ - function add(uint256 a, uint256 b) internal pure returns (uint256) { - uint256 c = a + b; - require(c >= a, "SafeMath: addition overflow"); - - return c; - } - - /** - * @dev Returns the subtraction of two unsigned integers, reverting on - * overflow (when the result is negative). - * - * Counterpart to Solidity's `-` operator. - * - * Requirements: - * - * - Subtraction cannot overflow. - */ - function sub(uint256 a, uint256 b) internal pure returns (uint256) { - return sub(a, b, "SafeMath: subtraction overflow"); - } - - /** - * @dev Returns the subtraction of two unsigned integers, reverting with custom message on - * overflow (when the result is negative). - * - * Counterpart to Solidity's `-` operator. - * - * Requirements: - * - * - Subtraction cannot overflow. - */ - function sub( - uint256 a, - uint256 b, - string memory errorMessage - ) internal pure returns (uint256) { - require(b <= a, errorMessage); - uint256 c = a - b; - - return c; - } - - /** - * @dev Returns the multiplication of two unsigned integers, reverting on - * overflow. - * - * Counterpart to Solidity's `*` operator. - * - * Requirements: - * - * - Multiplication cannot overflow. - */ - function mul(uint256 a, uint256 b) internal pure returns (uint256) { - // Gas optimization: this is cheaper than requiring 'a' not being zero, but the - // benefit is lost if 'b' is also tested. - // See: https://github.com/OpenZeppelin/openzeppelin-contracts/pull/522 - if (a == 0) { - return 0; - } - - uint256 c = a * b; - require(c / a == b, "SafeMath: multiplication overflow"); - - return c; - } - - /** - * @dev Returns the integer division of two unsigned integers. Reverts on - * division by zero. The result is rounded towards zero. - * - * Counterpart to Solidity's `/` operator. Note: this function uses a - * `revert` opcode (which leaves remaining gas untouched) while Solidity - * uses an invalid opcode to revert (consuming all remaining gas). - * - * Requirements: - * - * - The divisor cannot be zero. - */ - function div(uint256 a, uint256 b) internal pure returns (uint256) { - return div(a, b, "SafeMath: division by zero"); - } - - /** - * @dev Returns the integer division of two unsigned integers. Reverts with custom message on - * division by zero. The result is rounded towards zero. - * - * Counterpart to Solidity's `/` operator. Note: this function uses a - * `revert` opcode (which leaves remaining gas untouched) while Solidity - * uses an invalid opcode to revert (consuming all remaining gas). - * - * Requirements: - * - * - The divisor cannot be zero. - */ - function div( - uint256 a, - uint256 b, - string memory errorMessage - ) internal pure returns (uint256) { - require(b > 0, errorMessage); - uint256 c = a / b; - // assert(a == b * c + a % b); // There is no case in which this doesn't hold - - return c; - } - - /** - * @dev Returns the remainder of dividing two unsigned integers. (unsigned integer modulo), - * Reverts when dividing by zero. - * - * Counterpart to Solidity's `%` operator. This function uses a `revert` - * opcode (which leaves remaining gas untouched) while Solidity uses an - * invalid opcode to revert (consuming all remaining gas). - * - * Requirements: - * - * - The divisor cannot be zero. - */ - function mod(uint256 a, uint256 b) internal pure returns (uint256) { - return mod(a, b, "SafeMath: modulo by zero"); - } - - /** - * @dev Returns the remainder of dividing two unsigned integers. (unsigned integer modulo), - * Reverts with custom message when dividing by zero. - * - * Counterpart to Solidity's `%` operator. This function uses a `revert` - * opcode (which leaves remaining gas untouched) while Solidity uses an - * invalid opcode to revert (consuming all remaining gas). - * - * Requirements: - * - * - The divisor cannot be zero. - */ - function mod( - uint256 a, - uint256 b, - string memory errorMessage - ) internal pure returns (uint256) { - require(b != 0, errorMessage); - return a % b; - } - - // babylonian method (https://en.wikipedia.org/wiki/Methods_of_computing_square_roots#Babylonian_method) - function sqrrt(uint256 a) internal pure returns (uint256 c) { - if (a > 3) { - c = a; - uint256 b = add(div(a, 2), 1); - while (b < c) { - c = b; - b = div(add(div(a, b), b), 2); - } - } else if (a != 0) { - c = 1; - } - } - - /* - * Expects percentage to be trailed by 00, - */ - function percentageAmount(uint256 total_, uint8 percentage_) internal pure returns (uint256 percentAmount_) { - return div(mul(total_, percentage_), 1000); - } - - /* - * Expects percentage to be trailed by 00, - */ - function substractPercentage(uint256 total_, uint8 percentageToSub_) internal pure returns (uint256 result_) { - return sub(total_, div(mul(total_, percentageToSub_), 1000)); - } - - function percentageOfTotal(uint256 part_, uint256 total_) internal pure returns (uint256 percent_) { - return div(mul(part_, 100), total_); - } - - /** - * Taken from Hypersonic https://github.com/M2629/HyperSonic/blob/main/Math.sol - * @dev Returns the average of two numbers. The result is rounded towards - * zero. - */ - function average(uint256 a, uint256 b) internal pure returns (uint256) { - // (a + b) / 2 can overflow, so we distribute - return (a / 2) + (b / 2) + (((a % 2) + (b % 2)) / 2); - } - - function quadraticPricing(uint256 payment_, uint256 multiplier_) internal pure returns (uint256) { - return sqrrt(mul(multiplier_, payment_)); - } - - function bondingCurve(uint256 supply_, uint256 multiplier_) internal pure returns (uint256) { - return mul(multiplier_, supply_); - } -} - -// OpenZeppelin Contracts (last updated v4.7.0) (token/ERC20/utils/SafeERC20.sol) - - - - - -// OpenZeppelin Contracts v4.4.1 (token/ERC20/extensions/draft-IERC20Permit.sol) - - - -/** - * @dev Interface of the ERC20 Permit extension allowing approvals to be made via signatures, as defined in - * https://eips.ethereum.org/EIPS/eip-2612[EIP-2612]. - * - * Adds the {permit} method, which can be used to change an account's ERC20 allowance (see {IERC20-allowance}) by - * presenting a message signed by the account. By not relying on {IERC20-approve}, the token holder account doesn't - * need to send a transaction, and thus is not required to hold Ether at all. - */ -interface IERC20Permit { - /** - * @dev Sets `value` as the allowance of `spender` over ``owner``'s tokens, - * given ``owner``'s signed approval. - * - * IMPORTANT: The same issues {IERC20-approve} has related to transaction - * ordering also apply here. - * - * Emits an {Approval} event. - * - * Requirements: - * - * - `spender` cannot be the zero address. - * - `deadline` must be a timestamp in the future. - * - `v`, `r` and `s` must be a valid `secp256k1` signature from `owner` - * over the EIP712-formatted function arguments. - * - the signature must use ``owner``'s current nonce (see {nonces}). - * - * For more information on the signature format, see the - * https://eips.ethereum.org/EIPS/eip-2612#specification[relevant EIP - * section]. - */ - function permit( - address owner, - address spender, - uint256 value, - uint256 deadline, - uint8 v, - bytes32 r, - bytes32 s - ) external; - - /** - * @dev Returns the current nonce for `owner`. This value must be - * included whenever a signature is generated for {permit}. - * - * Every successful call to {permit} increases ``owner``'s nonce by one. This - * prevents a signature from being used multiple times. - */ - function nonces(address owner) external view returns (uint256); - - /** - * @dev Returns the domain separator used in the encoding of the signature for {permit}, as defined by {EIP712}. - */ - // solhint-disable-next-line func-name-mixedcase - function DOMAIN_SEPARATOR() external view returns (bytes32); -} - - - -/** - * @title SafeERC20 - * @dev Wrappers around ERC20 operations that throw on failure (when the token - * contract returns false). Tokens that return no value (and instead revert or - * throw on failure) are also supported, non-reverting calls are assumed to be - * successful. - * To use this library you can add a `using SafeERC20 for IERC20;` statement to your contract, - * which allows you to call the safe operations as `token.safeTransfer(...)`, etc. - */ -library SafeERC20 { - using Address for address; - - function safeTransfer( - IERC20 token, - address to, - uint256 value - ) internal { - _callOptionalReturn(token, abi.encodeWithSelector(token.transfer.selector, to, value)); - } - - function safeTransferFrom( - IERC20 token, - address from, - address to, - uint256 value - ) internal { - _callOptionalReturn(token, abi.encodeWithSelector(token.transferFrom.selector, from, to, value)); - } - - /** - * @dev Deprecated. This function has issues similar to the ones found in - * {IERC20-approve}, and its usage is discouraged. - * - * Whenever possible, use {safeIncreaseAllowance} and - * {safeDecreaseAllowance} instead. - */ - function safeApprove( - IERC20 token, - address spender, - uint256 value - ) internal { - // safeApprove should only be called when setting an initial allowance, - // or when resetting it to zero. To increase and decrease it, use - // 'safeIncreaseAllowance' and 'safeDecreaseAllowance' - require( - (value == 0) || (token.allowance(address(this), spender) == 0), - "SafeERC20: approve from non-zero to non-zero allowance" - ); - _callOptionalReturn(token, abi.encodeWithSelector(token.approve.selector, spender, value)); - } - - function safeIncreaseAllowance( - IERC20 token, - address spender, - uint256 value - ) internal { - uint256 newAllowance = token.allowance(address(this), spender) + value; - _callOptionalReturn(token, abi.encodeWithSelector(token.approve.selector, spender, newAllowance)); - } - - function safeDecreaseAllowance( - IERC20 token, - address spender, - uint256 value - ) internal { - unchecked { - uint256 oldAllowance = token.allowance(address(this), spender); - require(oldAllowance >= value, "SafeERC20: decreased allowance below zero"); - uint256 newAllowance = oldAllowance - value; - _callOptionalReturn(token, abi.encodeWithSelector(token.approve.selector, spender, newAllowance)); - } - } - - function safePermit( - IERC20Permit token, - address owner, - address spender, - uint256 value, - uint256 deadline, - uint8 v, - bytes32 r, - bytes32 s - ) internal { - uint256 nonceBefore = token.nonces(owner); - token.permit(owner, spender, value, deadline, v, r, s); - uint256 nonceAfter = token.nonces(owner); - require(nonceAfter == nonceBefore + 1, "SafeERC20: permit did not succeed"); - } - - /** - * @dev Imitates a Solidity high-level call (i.e. a regular function call to a contract), relaxing the requirement - * on the return value: the return value is optional (but if data is returned, it must not be false). - * @param token The token targeted by the call. - * @param data The call data (encoded using abi.encode or one of its variants). - */ - function _callOptionalReturn(IERC20 token, bytes memory data) private { - // We need to perform a low level call here, to bypass Solidity's return data size checking mechanism, since - // we're implementing it ourselves. We use {Address.functionCall} to perform this call, which verifies that - // the target address contains contract code and also asserts for success in the low-level call. - - bytes memory returndata = address(token).functionCall(data, "SafeERC20: low-level call failed"); - if (returndata.length > 0) { - // Return data is optional - require(abi.decode(returndata, (bool)), "SafeERC20: ERC20 operation did not succeed"); - } - } -} - - - - - - - - - - - - - - -/** - * @dev Provides information about the current execution context, including the - * sender of the transaction and its data. While these are generally available - * via msg.sender and msg.data, they should not be accessed in such a direct - * manner, since when dealing with meta-transactions the account sending and - * paying for execution may not be the actual sender (as far as an application - * is concerned). - * - * This contract is only required for intermediate, library-like contracts. - */ -abstract contract Context { - function _msgSender() internal view virtual returns (address) { - return msg.sender; - } - - function _msgData() internal view virtual returns (bytes calldata) { - return msg.data; - } -} - - -/** - * @dev Contract module which provides a basic access control mechanism, where - * there is an account (an owner) that can be granted exclusive access to - * specific functions. - * - * By default, the owner account will be the one that deploys the contract. This - * can later be changed with {transferOwnership}. - * - * This module is used through inheritance. It will make available the modifier - * `onlyOwner`, which can be applied to your functions to restrict their use to - * the owner. - */ -abstract contract Ownable is Context { - address private _owner; - - event OwnershipTransferred(address indexed previousOwner, address indexed newOwner); - - /** - * @dev Initializes the contract setting the deployer as the initial owner. - */ - constructor() { - _transferOwnership(_msgSender()); - } - - /** - * @dev Throws if called by any account other than the owner. - */ - modifier onlyOwner() { - _checkOwner(); - _; - } - - /** - * @dev Returns the address of the current owner. - */ - function owner() public view virtual returns (address) { - return _owner; - } - - /** - * @dev Throws if the sender is not the owner. - */ - function _checkOwner() internal view virtual { - require(owner() == _msgSender(), "Ownable: caller is not the owner"); - } - - /** - * @dev Leaves the contract without owner. It will not be possible to call - * `onlyOwner` functions anymore. Can only be called by the current owner. - * - * NOTE: Renouncing ownership will leave the contract without an owner, - * thereby removing any functionality that is only available to the owner. - */ - function renounceOwnership() public virtual onlyOwner { - _transferOwnership(address(0)); - } - - /** - * @dev Transfers ownership of the contract to a new account (`newOwner`). - * Can only be called by the current owner. - */ - function transferOwnership(address newOwner) public virtual onlyOwner { - require(newOwner != address(0), "Ownable: new owner is the zero address"); - _transferOwnership(newOwner); - } - - /** - * @dev Transfers ownership of the contract to a new account (`newOwner`). - * Internal function without access restriction. - */ - function _transferOwnership(address newOwner) internal virtual { - address oldOwner = _owner; - _owner = newOwner; - emit OwnershipTransferred(oldOwner, newOwner); - } -} - - -contract Operator is Ownable { - address public operator; - uint256 constant baseRate = 10000; - - modifier onlyOperator { - require(msg.sender == owner() || msg.sender == operator, "no permission"); - _; - } - - function setOperator(address operator_) external onlyOwner { - operator = operator_; - } - - - function getCurrTime() external view returns(uint256) { - return block.timestamp; - } - - function getBlockNum() external view returns(uint256) { - return block.number; - } - -} - - - - - -/** - * @dev Library for managing - * https://en.wikipedia.org/wiki/Set_(abstract_data_type)[sets] of primitive - * types. - * - * Sets have the following properties: - * - * - Elements are added, removed, and checked for existence in constant time - * (O(1)). - * - Elements are enumerated in O(n). No guarantees are made on the ordering. - * - * ``` - * contract Example { - * // Add the library methods - * using EnumerableSet for EnumerableSet.AddressSet; - * - * // Declare a set state variable - * EnumerableSet.AddressSet private mySet; - * } - * ``` - * - * As of v3.3.0, sets of type `bytes32` (`Bytes32Set`), `address` (`AddressSet`) - * and `uint256` (`UintSet`) are supported. - * - * [WARNING] - * ==== - * Trying to delete such a structure from storage will likely result in data corruption, rendering the structure unusable. - * See https://github.com/ethereum/solidity/pull/11843[ethereum/solidity#11843] for more info. - * - * In order to clean an EnumerableSet, you can either remove all elements one by one or create a fresh instance using an array of EnumerableSet. - * ==== - */ - -library EnumerableSet { - // To implement this library for multiple types with as little code - // repetition as possible, we write it in terms of a generic Set type with - // bytes32 values. - // The Set implementation uses private functions, and user-facing - // implementations (such as AddressSet) are just wrappers around the - // underlying Set. - // This means that we can only create new EnumerableSets for types that fit - // in bytes32. - - struct Set { - // Storage of set values - bytes32[] _values; - // Position of the value in the `values` array, plus 1 because index 0 - // means a value is not in the set. - mapping(bytes32 => uint256) _indexes; - } - - /** - * @dev Add a value to a set. O(1). - * - * Returns true if the value was added to the set, that is if it was not - * already present. - */ - function _add(Set storage set, bytes32 value) private returns (bool) { - if (!_contains(set, value)) { - set._values.push(value); - // The value is stored at length-1, but we add 1 to all indexes - // and use 0 as a sentinel value - set._indexes[value] = set._values.length; - return true; - } else { - return false; - } - } - - /** - * @dev Removes a value from a set. O(1). - * - * Returns true if the value was removed from the set, that is if it was - * present. - */ - function _remove(Set storage set, bytes32 value) private returns (bool) { - // We read and store the value's index to prevent multiple reads from the same storage slot - uint256 valueIndex = set._indexes[value]; - - if (valueIndex != 0) { - // Equivalent to contains(set, value) - // To delete an element from the _values array in O(1), we swap the element to delete with the last one in - // the array, and then remove the last element (sometimes called as 'swap and pop'). - // This modifies the order of the array, as noted in {at}. - - uint256 toDeleteIndex = valueIndex - 1; - uint256 lastIndex = set._values.length - 1; - - if (lastIndex != toDeleteIndex) { - bytes32 lastValue = set._values[lastIndex]; - - // Move the last value to the index where the value to delete is - set._values[toDeleteIndex] = lastValue; - // Update the index for the moved value - set._indexes[lastValue] = valueIndex; // Replace lastValue's index to valueIndex - } - - // Delete the slot where the moved value was stored - set._values.pop(); - - // Delete the index for the deleted slot - delete set._indexes[value]; - - return true; - } else { - return false; - } - } - - /** - * @dev Returns true if the value is in the set. O(1). - */ - function _contains(Set storage set, bytes32 value) private view returns (bool) { - return set._indexes[value] != 0; - } - - /** - * @dev Returns the number of values on the set. O(1). - */ - function _length(Set storage set) private view returns (uint256) { - return set._values.length; - } - - /** - * @dev Returns the value stored at position `index` in the set. O(1). - * - * Note that there are no guarantees on the ordering of values inside the - * array, and it may change when more values are added or removed. - * - * Requirements: - * - * - `index` must be strictly less than {length}. - */ - function _at(Set storage set, uint256 index) private view returns (bytes32) { - return set._values[index]; - } - - /** - * @dev Return the entire set in an array - * - * WARNING: This operation will copy the entire storage to memory, which can be quite expensive. This is designed - * to mostly be used by view accessors that are queried without any gas fees. Developers should keep in mind that - * this function has an unbounded cost, and using it as part of a state-changing function may render the function - * uncallable if the set grows to a point where copying to memory consumes too much gas to fit in a block. - */ - function _values(Set storage set) private view returns (bytes32[] memory) { - return set._values; - } - - // Bytes32Set - - struct Bytes32Set { - Set _inner; - } - - /** - * @dev Add a value to a set. O(1). - * - * Returns true if the value was added to the set, that is if it was not - * already present. - */ - function add(Bytes32Set storage set, bytes32 value) internal returns (bool) { - return _add(set._inner, value); - } - - /** - * @dev Removes a value from a set. O(1). - * - * Returns true if the value was removed from the set, that is if it was - * present. - */ - function remove(Bytes32Set storage set, bytes32 value) internal returns (bool) { - return _remove(set._inner, value); - } - - /** - * @dev Returns true if the value is in the set. O(1). - */ - function contains(Bytes32Set storage set, bytes32 value) internal view returns (bool) { - return _contains(set._inner, value); - } - - /** - * @dev Returns the number of values in the set. O(1). - */ - function length(Bytes32Set storage set) internal view returns (uint256) { - return _length(set._inner); - } - - /** - * @dev Returns the value stored at position `index` in the set. O(1). - * - * Note that there are no guarantees on the ordering of values inside the - * array, and it may change when more values are added or removed. - * - * Requirements: - * - * - `index` must be strictly less than {length}. - */ - function at(Bytes32Set storage set, uint256 index) internal view returns (bytes32) { - return _at(set._inner, index); - } - - /** - * @dev Return the entire set in an array - * - * WARNING: This operation will copy the entire storage to memory, which can be quite expensive. This is designed - * to mostly be used by view accessors that are queried without any gas fees. Developers should keep in mind that - * this function has an unbounded cost, and using it as part of a state-changing function may render the function - * uncallable if the set grows to a point where copying to memory consumes too much gas to fit in a block. - */ - function values(Bytes32Set storage set) internal view returns (bytes32[] memory) { - return _values(set._inner); - } - - // AddressSet - - struct AddressSet { - Set _inner; - } - - /** - * @dev Add a value to a set. O(1). - * - * Returns true if the value was added to the set, that is if it was not - * already present. - */ - function add(AddressSet storage set, address value) internal returns (bool) { - return _add(set._inner, bytes32(uint256(uint160(value)))); - } - - /** - * @dev Removes a value from a set. O(1). - * - * Returns true if the value was removed from the set, that is if it was - * present. - */ - function remove(AddressSet storage set, address value) internal returns (bool) { - return _remove(set._inner, bytes32(uint256(uint160(value)))); - } - - /** - * @dev Returns true if the value is in the set. O(1). - */ - function contains(AddressSet storage set, address value) internal view returns (bool) { - return _contains(set._inner, bytes32(uint256(uint160(value)))); - } - - /** - * @dev Returns the number of values in the set. O(1). - */ - function length(AddressSet storage set) internal view returns (uint256) { - return _length(set._inner); - } - - /** - * @dev Returns the value stored at position `index` in the set. O(1). - * - * Note that there are no guarantees on the ordering of values inside the - * array, and it may change when more values are added or removed. - * - * Requirements: - * - * - `index` must be strictly less than {length}. - */ - function at(AddressSet storage set, uint256 index) internal view returns (address) { - return address(uint160(uint256(_at(set._inner, index)))); - } - - /** - * @dev Return the entire set in an array - * - * WARNING: This operation will copy the entire storage to memory, which can be quite expensive. This is designed - * to mostly be used by view accessors that are queried without any gas fees. Developers should keep in mind that - * this function has an unbounded cost, and using it as part of a state-changing function may render the function - * uncallable if the set grows to a point where copying to memory consumes too much gas to fit in a block. - */ - function values(AddressSet storage set) internal view returns (address[] memory) { - bytes32[] memory store = _values(set._inner); - address[] memory result; - - /// @solidity memory-safe-assembly - assembly { - result := store - } - - return result; - } - - // UintSet - - struct UintSet { - Set _inner; - } - - /** - * @dev Add a value to a set. O(1). - * - * Returns true if the value was added to the set, that is if it was not - * already present. - */ - function add(UintSet storage set, uint256 value) internal returns (bool) { - return _add(set._inner, bytes32(value)); - } - - /** - * @dev Removes a value from a set. O(1). - * - * Returns true if the value was removed from the set, that is if it was - * present. - */ - function remove(UintSet storage set, uint256 value) internal returns (bool) { - return _remove(set._inner, bytes32(value)); - } - - /** - * @dev Returns true if the value is in the set. O(1). - */ - function contains(UintSet storage set, uint256 value) internal view returns (bool) { - return _contains(set._inner, bytes32(value)); - } - - /** - * @dev Returns the number of values on the set. O(1). - */ - function length(UintSet storage set) internal view returns (uint256) { - return _length(set._inner); - } - - /** - * @dev Returns the value stored at position `index` in the set. O(1). - * - * Note that there are no guarantees on the ordering of values inside the - * array, and it may change when more values are added or removed. - * - * Requirements: - * - * - `index` must be strictly less than {length}. - */ - function at(UintSet storage set, uint256 index) internal view returns (uint256) { - return uint256(_at(set._inner, index)); - } - - /** - * @dev Return the entire set in an array - * - * WARNING: This operation will copy the entire storage to memory, which can be quite expensive. This is designed - * to mostly be used by view accessors that are queried without any gas fees. Developers should keep in mind that - * this function has an unbounded cost, and using it as part of a state-changing function may render the function - * uncallable if the set grows to a point where copying to memory consumes too much gas to fit in a block. - */ - function values(UintSet storage set) internal view returns (uint256[] memory) { - bytes32[] memory store = _values(set._inner); - uint256[] memory result; - - /// @solidity memory-safe-assembly - assembly { - result := store - } - - return result; - } -} - - -contract ActivityPool is Operator { - using SafeMath for uint256; - using SafeERC20 for IERC20; - using EnumerableSet for EnumerableSet.AddressSet; - using EnumerableSet for EnumerableSet.UintSet; - - event AddNewAct(uint256 id); - event Bet(address user, uint256 pID, uint256 bType, uint256 amount, uint256 time); - event SetPrize(uint256 pID, uint256 bType); - event Claim(address user, uint256 pID, uint256 bType, uint256 amount); - event RemovePeriodAct(uint256 pID); - - uint256 public constant muti = 1e18; - uint256 public periodID; - uint256 public betID; - - struct UserInfo { - address user; - uint256 pID; - uint256 amount; - uint256 betTime; - uint256 bType; - uint256 claimAmount; - } - - struct ActInfo { - string name; - string aName; - string bName; - address rewardToken; - uint256 startTime; - uint256 endTime; - uint256 minAmount; - uint256 maxAmount; - uint256 aAmount; - uint256 bAmount; - uint256 winType; - bool isBet; - } - - struct TimeInfo { - uint256 time; - uint256 aAmount; - uint256 bAmount; - } - - struct BestInfo { - address aUser; - address bUser; - uint256 aBet; - uint256 bBet; - } - - mapping(uint256 => BestInfo) bestInfo; - mapping(uint256 => uint256) public timeID; - mapping(uint256 => mapping(uint256 => TimeInfo)) public timeInfo; - mapping(address => mapping(uint256 => uint256)) public userBet; - mapping(uint256 => UserInfo) public betInfo; - mapping(uint256 => uint256) public perAmount; - mapping(uint256 => ActInfo) public actInfo; - mapping(uint256 => mapping(uint256 => string)) public descripName; - - mapping(address => EnumerableSet.UintSet) userPid; - mapping(uint256 => EnumerableSet.AddressSet) aUsers; - mapping(uint256 => EnumerableSet.AddressSet) bUsers; - EnumerableSet.UintSet activePeriod; - EnumerableSet.UintSet removePeriod; - - function addNewAct( - string memory name, - string memory aName, - string memory bName, - address token, - uint256 startTime, - uint256 endTime, - uint256 minAmount, - uint256 maxAmount - ) external onlyOperator { - - checkAdd(msg.sender, startTime, endTime, minAmount, maxAmount); - uint256 id = ++periodID; - actInfo[id].name = name; - actInfo[id].aName = aName; - actInfo[id].bName = bName; - actInfo[id].startTime = startTime; - actInfo[id].endTime = endTime; - actInfo[id].minAmount = minAmount; - actInfo[id].maxAmount = maxAmount; - actInfo[id].rewardToken = token; - descripName[id][1] = aName; - descripName[id][2] = bName; - activePeriod.add(id); - - emit AddNewAct(id); - } - - - function removePeriodAct(uint256 pID) external onlyOperator { - checkRemove(pID); - - activePeriod.remove(pID); - removePeriod.add(pID); - - emit RemovePeriodAct(pID); - } - - - function bet(uint256 pID, uint256 bType, uint256 amount) external payable { - checkBet(msg.sender, pID, bType, amount); - if(actInfo[pID].rewardToken == address(0)) { - require(msg.value == amount, "value err"); - } else { - require(msg.value == 0, "value amount err"); - } - - if(bType == 1) { - if(amount > bestInfo[pID].aBet) { - bestInfo[pID].aUser = msg.sender; - bestInfo[pID].aBet = amount; - } - } else { - if(amount > bestInfo[pID].bBet) { - bestInfo[pID].bUser = msg.sender; - bestInfo[pID].bBet = amount; - } - } - - userPid[msg.sender].add(pID); - uint256 id = ++betID; - userBet[msg.sender][pID] = id; - - if(bType == 1) { - aUsers[pID].add(msg.sender); - actInfo[pID].aAmount = actInfo[pID].aAmount.add(amount); - } else { - bUsers[pID].add(msg.sender); - actInfo[pID].bAmount = actInfo[pID].bAmount.add(amount); - } - - actInfo[pID].isBet = true; - betInfo[id].user = msg.sender; - betInfo[id].pID = pID; - betInfo[id].amount = amount; - betInfo[id].betTime = block.timestamp; - betInfo[id].bType = bType; - - uint256 tID = ++timeID[pID]; - timeInfo[pID][tID].time = block.timestamp; - timeInfo[pID][tID].aAmount = actInfo[pID].aAmount; - timeInfo[pID][tID].bAmount = actInfo[pID].bAmount; - - if(actInfo[pID].rewardToken != address(0)) { - IERC20(actInfo[pID].rewardToken).safeTransferFrom(msg.sender, address(this), amount); - } - emit Bet(msg.sender, pID, bType, amount, betInfo[id].betTime); - } - - function setPrize(uint256 pID, uint256 bType) external onlyOperator { - checkSetPrize(msg.sender, pID, bType); - - if(block.timestamp <= actInfo[pID].startTime) { - actInfo[pID].startTime = block.timestamp; - - } - actInfo[pID].endTime = block.timestamp; - - actInfo[pID].winType = bType; - perAmount[pID] = getPerAmount(pID, bType); - - emit SetPrize(pID, bType); - } - - function recive() public payable {} - - function claim(uint256 pID) external { - uint256 amount = checkClaim(msg.sender, pID); - - uint256 id = userBet[msg.sender][pID]; - betInfo[id].claimAmount = amount; - if(actInfo[pID].rewardToken != address(0)) { - IERC20(actInfo[pID].rewardToken).safeTransfer(msg.sender, amount); - } else { - payable(msg.sender).transfer(amount); - } - - emit Claim(msg.sender, pID, betInfo[id].bType, amount); - } - - function checkClaim(address user, uint256 pID) public view returns(uint256 amount) { - require(userPid[user].contains(pID), "not bet"); - uint256 id = userBet[user][pID]; - require(betInfo[id].user == user, "not user"); - require(actInfo[pID].winType != 0, "not prize"); - require(betInfo[id].claimAmount == 0, "has claim"); - - if(actInfo[pID].winType != 3) { - require(actInfo[pID].winType == betInfo[id].bType, "not right"); - amount = perAmount[pID].mul(betInfo[id].amount).div(muti); - require(amount > 0, "no amount"); - } else { - amount = betInfo[id].amount; - } - - return amount; - } - - function getActualRate( - address user, - uint256 pID, - uint256 bType, - uint256 amount - ) external view returns(uint256, uint256, bool) { - if(bType < 1 || bType > 2 || !activePeriod.contains(pID)) { - return (0, 0, false); - } else if(userBet[user][pID] != 0 || actInfo[pID].winType != 0 || amount == 0) { - (uint256 ra, uint256 rb) = getRate(pID, timeID[pID]); - return (ra, rb, false); - } else { - (uint256 aAmount, uint256 bAmount) = (actInfo[pID].aAmount, actInfo[pID].bAmount); - if(bType == 1) { - aAmount = aAmount.add(amount); - } else { - bAmount = bAmount.add(amount); - } - - uint256 total = aAmount.add(bAmount); - if(bAmount == 0 && aAmount != 0) { - return (muti, 0, true); - } - if(bAmount != 0 && aAmount == 0) { - return (0, muti, true); - } - return (total.mul(muti).div(aAmount), total.mul(muti).div(bAmount), true); - } - } - - function getRate(uint256 pID, uint256 tID) public view returns(uint256, uint256) { - (uint256 aAmount, uint256 bAmount) = (timeInfo[pID][tID].aAmount, timeInfo[pID][tID].bAmount); - uint256 total = aAmount.add(bAmount); - if(total == 0) { - return (0, 0); - } - if(bAmount == 0 && aAmount != 0) { - return (muti, 0); - } - if(bAmount != 0 && aAmount == 0) { - return (0, muti); - } - return (total.mul(muti).div(aAmount), total.mul(muti).div(bAmount)); - } - - function getBestInfo(uint256 pID) - external - view - returns(address aUser, address bUser, uint256 aBet, uint256 bBet, uint256 aReward, uint256 bReward) - { - aUser = bestInfo[pID].aUser; - bUser = bestInfo[pID].bUser; - aBet = bestInfo[pID].aBet; - bBet = bestInfo[pID].bBet; - aReward = getPerAmount(pID, 1).mul(aBet).div(muti); - bReward = getPerAmount(pID, 2).mul(bBet).div(muti); - } - - function getPerAmount(uint256 pID, uint256 bType) public view returns(uint256) { - uint256 total = actInfo[pID].aAmount.add(actInfo[pID].bAmount); - if(total == 0) { - return 0; - } - - if(actInfo[pID].winType == 3) { - return muti; - } - - if(bType == 1) { - if(actInfo[pID].aAmount == 0 || actInfo[pID].winType == 2) { - return 0; - } - return total.mul(muti).div(actInfo[pID].aAmount); - } - - if(bType == 2) { - if(actInfo[pID].bAmount == 0 || actInfo[pID].winType == 1) { - return 0; - } - return total.mul(muti).div(actInfo[pID].bAmount); - } - - return 0; - - } - - function checkSetPrize(address user, uint256 pID, uint256 bType) public view returns(bool) { - require(user == owner() || user == operator, "no permission"); - require(bType > 0 && bType <= 3, "type err"); - require(activePeriod.contains(pID), "not active"); - require(actInfo[pID].winType == 0, "has set"); - - return true; - } - - function checkBet( - address user, - uint256 pID, - uint256 bType, - uint256 amount - ) public view returns(bool) { - require(activePeriod.contains(pID), "not active"); - require(actInfo[pID].startTime <= block.timestamp, "not start"); - require(actInfo[pID].endTime > block.timestamp, "has end"); - require(!userPid[user].contains(pID), "has bet"); - require(bType > 0 && bType < 3, "type err"); - require(amount >= actInfo[pID].minAmount && amount <= actInfo[pID].maxAmount, "amount err"); - if(actInfo[pID].rewardToken != address(0)) { - require(IERC20(actInfo[pID].rewardToken).allowance(user, address(this)) >= amount, "not approve enough"); - require(IERC20(actInfo[pID].rewardToken).balanceOf(user) >= amount, "not enough"); - } else { - require(user.balance >= amount, "main token err"); - } - - return true; - } - - - function checkRemove(uint256 pID) public view returns(bool) { - require(activePeriod.contains(pID), "not in"); - require(!actInfo[pID].isBet, "has bet"); - - return true; - } - - function checkAdd( - address user, - uint256 startTime, - uint256 endTime, - uint256 minAmount, - uint256 maxAmount - ) public view returns(bool) { - require(user == owner() || user == operator, "no permission"); - require(startTime > block.timestamp, "startTime err"); - require(endTime > startTime, "endTime err"); - require(minAmount > 0 && maxAmount > minAmount, "amount err"); - - return true; - } - - function getStatus(uint256 pID) external view returns(uint256) { - if(!removePeriod.contains(pID) && !activePeriod.contains(pID)) { - return 5; - } else if(removePeriod.contains(pID)) { - return 6; - } else if(block.timestamp < actInfo[pID].startTime) { - return 1; - } else if ( - actInfo[pID].startTime <= block.timestamp && - actInfo[pID].endTime > block.timestamp - ) { - return 2; - } else if (actInfo[pID].endTime <= block.timestamp && actInfo[pID].winType == 0){ - return 3; - } else if(actInfo[pID].winType != 0) { - return 4; - } - return 0; - } - - function getUserPidNum(address user) external view returns(uint256) { - return userPid[user].length(); - } - - function getUserPid(address user, uint256 index) external view returns(uint256) { - return userPid[user].at(index); - } - - function getAUsersNum(uint256 pID) external view returns(uint256) { - return aUsers[pID].length(); - } - - function getAUsers(uint256 pID, uint256 index) external view returns(address) { - return aUsers[pID].at(index); - } - - function getBUsersNum(uint256 pID) external view returns(uint256) { - return bUsers[pID].length(); - } - - function getBUsers(uint256 pID, uint256 index) external view returns(address) { - return bUsers[pID].at(index); - } - - function getActivePeriodNum() external view returns(uint256) { - return activePeriod.length(); - } - - function getActivePeriod(uint256 index) external view returns(uint256) { - return activePeriod.at(index); - } - - function getRemovePeriodNum() external view returns(uint256) { - return removePeriod.length(); - } - - function getRemovePeriod(uint256 index) external view returns(uint256) { - return removePeriod.at(index); - } -} \ No newline at end of file diff --git a/app/api/uploads/Test_1-1729808659268-441728940.sol b/app/api/uploads/Test_1-1729808659268-441728940.sol deleted file mode 100644 index 3228ff2..0000000 --- a/app/api/uploads/Test_1-1729808659268-441728940.sol +++ /dev/null @@ -1,143 +0,0 @@ -// SPDX-License-Identifier: MIT -pragma solidity ^0.8.0; - -contract VulnerableContract { - // State variables - uint256 private counter; - address public owner; - mapping(address => uint256) public balances; - bool private locked; - uint256[] public values; - - // Events - event Transfer(address indexed from, address indexed to, uint256 amount); - event Deposit(address indexed user, uint256 amount); - event OwnershipTransferred(address indexed previousOwner, address indexed newOwner); - - constructor() { - owner = msg.sender; - } - - function setOwner(address _newOwner) public { - owner = _newOwner; - } - - function withdraw(uint256 _amount) public { - require(balances[msg.sender] >= _amount, "Insufficient balance"); - (bool success, ) = msg.sender.call{value: _amount}(""); - require(success, "Transfer failed"); - balances[msg.sender] -= _amount; - } - - function increment() public { - counter++; - } - - function transfer(address _to, uint256 _amount) public { - payable(_to).transfer(_amount); - } - - function isOwner() public view returns (bool) { - return tx.origin == owner; - } - - function deposit() public payable { - balances[msg.sender] += msg.value; - } - - function getBalance() public view returns (uint256) { - return balances[msg.sender] + balances[msg.sender]; - } - - // Missing zero-address check - function approve(address _spender, uint256 _value) public { - allowed[msg.sender][_spender] = _value; - } - - uint256 public totalSupply; - mapping(address => mapping(address => uint256)) public allowed; - - function processValues() public { - for(uint i = 0; i < values.length; i++) { - values[i] = values[i] * 2; - } - } - - function updateConfig(uint256 _value) public { - require(msg.sender == owner, "Not owner"); - counter = _value; - } - - function getName() public pure returns (string memory) { - return "VulnerableContract"; - } - - uint256 private unusedVar; - - function setValues(uint256[] memory _values) public { - values = _values; - } - - function riskyOperation() public { - require(msg.sender != address(0), "Zero address"); - locked = true; - } - - function getBlockHash() public view returns (bytes32) { - return blockhash(block.number - 1); - } - - function inefficientLoop() public { - uint256[] memory tempArray = new uint256[](100); - for(uint i = 0; i < tempArray.length; i++) { - tempArray[i] = i; - } - } - - function destroyContract() public { - selfdestruct(payable(msg.sender)); - } - - function transferOwnership(address _newOwner) public { - require(msg.sender == owner, "Not owner"); - owner = _newOwner; - } - - function multiply(uint256 a, uint256 b) public pure returns (uint256) { - return a * b; - } - - function helperFunction() internal { - counter += 1; - } - - function unusedParams(uint256 _unused, string memory _alsounused) public { - counter += 1; - } - - function riskyCall(address _target) public { - _target.call(""); - } - - modifier onlyOwner { - require(msg.sender == owner, "Not owner"); - require(msg.sender == owner, "Not owner"); - _; - } - - receive() external payable {} - - function processArray(uint256[] memory _array) public { - for(uint i = 0; i < 10; i++) { - values.push(_array[i]); - } - } - - function useAssembly() public view returns (uint size) { - assembly { - size := extcodesize(caller()) - } - } - - string constant private CONSTANT_STRING = "This is a very long string that could be shortened"; -} \ No newline at end of file diff --git a/components/button/upload-form.tsx b/components/button/upload-form.tsx index 9122ba3..54987a4 100644 --- a/components/button/upload-form.tsx +++ b/components/button/upload-form.tsx @@ -109,9 +109,11 @@ const UploadForm = ({style, title}: UploadFormProps) => { }); if (analyzeResponse.data.status === 'success') { + const metricsId = analyzeResponse.data.data.id; + + localStorage.setItem('metricsId', metricsId); setMessage('Upload successful! The scan has started.'); startScanning(analyzeResponse.data.data); - // Clear form setProjectName(''); setContractFile(null); diff --git a/components/section/contract-scan-result-section.tsx b/components/section/contract-scan-result-section.tsx index 05f82fa..ff2fcbd 100644 --- a/components/section/contract-scan-result-section.tsx +++ b/components/section/contract-scan-result-section.tsx @@ -1,7 +1,8 @@ import React, { useState, useEffect } from 'react'; -import { CustomButton, ResultBody, useScanning} from '@/components/index'; +import { CustomButton, ResultBody } from '@/components/index'; import { createClient } from '@supabase/supabase-js'; +// Types and Interfaces interface AnalysisMetrics { id: string; project_name: string; @@ -17,21 +18,26 @@ interface AnalysisMetrics { high_issues: number; ercs: string; } -// CircularProgress.tsx + +interface AnalysisVulns { + vulnerability: string; +} + interface CircularProgressProps { - value: number; // value between 0-100 - size?: number; // size in pixels - strokeWidth?: number; // border width - primaryColor?: string; // main color - secondaryColor?: string; // background color + value: number; + size?: number; + strokeWidth?: number; + primaryColor?: string; + secondaryColor?: string; } +// CircularProgress Component const CircularProgress: React.FC = ({ value, size = 48, strokeWidth = 4, - primaryColor = '#4F46E5', // indigo-600 - secondaryColor = '#E5E7EB' // gray-200 + primaryColor = '#4F46E5', + secondaryColor = '#E5E7EB' }) => { const radius = (size - strokeWidth) / 2; const circumference = radius * 2 * Math.PI; @@ -39,7 +45,6 @@ const CircularProgress: React.FC = ({ return (
- {/* Background circle */} = ({ stroke={secondaryColor} strokeWidth={strokeWidth} /> - {/* Foreground circle */} = ({ strokeDasharray={circumference} strokeDashoffset={offset} className="transition-all duration-500 ease-out" - style={{ - strokeLinecap: 'round' - }} + style={{ strokeLinecap: 'round' }} />
); }; -const ContractScanResult = () => { +// Utility functions +const calculateSafetyScore = (metrics: AnalysisMetrics): number => { + if (!metrics) return 0; + + const maxScore = 100; + const deductions = { + high: 6, + medium: 2, + low: 1 + }; + + const totalDeduction = + (metrics.high_issues * deductions.high) + + (metrics.medium_issues * deductions.medium) + + (metrics.low_issues * deductions.low); + + return Math.max(0, Math.min(100, maxScore - totalDeduction)); +}; + +// Main Component +const ContractScanResult: React.FC = () => { const [metrics, setMetrics] = useState(null); + const [vulns, setVulns] = useState(null); const [loading, setLoading] = useState(true); const [error, setError] = useState(null); + useEffect(() => { + let isMounted = true; + const fetchResults = async () => { try { + setLoading(true); + setError(null); + const supabase = createClient( process.env.NEXT_PUBLIC_SUPABASE_URL!, process.env.NEXT_PUBLIC_SUPABASE_ANON_KEY! ); - const { data, error } = await supabase + // Fetch metrics + const { data: metricsData, error: metricsError } = await supabase .from('slither_metrics') .select('*') .order('created_at', { ascending: false }) .limit(1) .single(); - if (error) throw error; - setMetrics(data); + if (metricsError) throw metricsError; + if (!metricsData) throw new Error('No metrics data found'); + + if (isMounted) { + setMetrics(metricsData); + + // Fetch vulnerabilities + const { data: vulnsData, error: vulnsError } = await supabase + .from('vulnerabilities') + .select('metrics_id, vulnerability') + .eq('metrics_id', metricsData.id) + .limit(93); + + if (vulnsError) throw vulnsError; + setVulns(vulnsData || []); + } } catch (error) { - console.error('Error fetching metrics:', error); - setError(error instanceof Error ? error.message : 'Failed to fetch analysis results'); + if (isMounted) { + console.error('Error fetching data:', error); + setError(error instanceof Error ? error.message : 'An error occurred'); + } } finally { - setLoading(false); + if (isMounted) { + setLoading(false); + } } }; fetchResults(); - }, []); - // Calculate safety score based on issues - const calculateSafetyScore = (metrics: AnalysisMetrics): number => { - if (!metrics) return 0; - - const maxScore = 100; - const deductions = { - high: 6, // Deduct 15 points per high issue - medium: 2, // Deduct 10 points per medium issue - low: 1 // Deduct 5 points per low issue + return () => { + isMounted = false; }; - - const totalDeduction = - (metrics.high_issues * deductions.high) + - (metrics.medium_issues * deductions.medium) + - (metrics.low_issues * deductions.low); - - return Math.max(0, Math.min(100, maxScore - totalDeduction)); - }; + }, []); const handleRedirectToPdf = () => { - const pdfUrl = '/contract/scanresult'; - window.open(pdfUrl, '_blank'); + window.open('/contract/scanresult', '_blank'); }; if (loading) { @@ -136,124 +168,118 @@ const ContractScanResult = () => { if (error || !metrics) { return (
-
Failed to load analysis results
+
+ {error || 'Failed to load analysis results'} +
); } const safetyScore = calculateSafetyScore(metrics); + const totalIssues = metrics.high_issues + metrics.medium_issues + + metrics.low_issues + metrics.informational_issues + + metrics.optimization_issues; return ( -
-
+
+
{/* Header section */} -
- {/* Top section with file info and generate button */} -
-
-
- solidity file -
-
-

{metrics.project_name}

-

File Scan

-
-
- - {/* Export button */} - - - } - title="Generate report" - containerStyles="bg-primary-red text-white font-semibold rounded-full px-4 py-2 lg:py-3 shadow-glow-red transition-all duration-300 ease-in-out transform hover:scale-105" - handleClick={handleRedirectToPdf} - /> -
- - {/* Metrics section */} -
- {/* Security Score */} -
- - {/* Security Score */} - - -
-

Security Score

-

- {safetyScore.toFixed(2)}/100 -

-
-
- - {/* Scan Duration */} -
-
- scan duration -
-
-

Scan duration

-

- {metrics.scan_duration} - secs

-
-
- - {/* Lines of Code */} -
-
- line of code -
-
-

Lines of code

-

{metrics.source_lines}

-
-
- - {/* Issues Count */} -
-
- issues count -
-
-

Issues Count

-

- {metrics.high_issues + metrics.medium_issues + metrics.low_issues + metrics.informational_issues + metrics.optimization_issues} -

-
-
-
-
- - - - - - - - - - - - +
+ {/* Top section */} +
+
+
+ solidity file +
+
+

{metrics.project_name}

+

File Scan

+
+
+ + {/* Export button */} + + + + } + title="Generate report" + containerStyles="bg-primary-red text-white font-semibold rounded-full px-4 py-2 lg:py-3 shadow-glow-red transition-all duration-300 ease-in-out transform hover:scale-105" + handleClick={handleRedirectToPdf} + /> +
+ {/* Metrics grid */} +
+ {/* Security Score */} +
+ +
+

Security Score

+

+ {safetyScore.toFixed(2)} + /100 +

+
+
+ + {/* Scan Duration */} +
+
+ scan duration +
+
+

Scan duration

+

+ {metrics.scan_duration} + secs +

+
+
+ + {/* Lines of Code */} +
+
+ line of code +
+
+

Lines of code

+

{metrics.source_lines}

+
+
+ + {/* Issues Count */} +
+
+ issues count +
+
+

Issues Count

+

{totalIssues}

+
+
+
+
{/* Main content area */} -
- {/* Safety check component */} -
- -
- - {/* Metrics Overview */} -
- +
+
+
diff --git a/components/section/overview.tsx b/components/section/overview.tsx index b707dc1..b555807 100644 --- a/components/section/overview.tsx +++ b/components/section/overview.tsx @@ -1,7 +1,5 @@ import React from 'react' -import { useState, useEffect } from 'react'; -import { createClient } from '@supabase/supabase-js'; -import { RadarChart, DonutChart, CopyButton } from '@/components/index' +import { DonutChart, CopyButton } from '@/components/index' interface AnalysisMetrics { id: string; @@ -16,39 +14,12 @@ interface AnalysisMetrics { high_issues: number; ercs: string; } +interface OverviewProps { + metrics: AnalysisMetrics | null; +} -export const Overview = () => { - const [metrics, setMetrics] = useState(null); - const [loading, setLoading] = useState(true); - const [error, setError] = useState(null); - - useEffect(() => { - const fetchResults = async () => { - try { - const supabase = createClient( - process.env.NEXT_PUBLIC_SUPABASE_URL!, - process.env.NEXT_PUBLIC_SUPABASE_ANON_KEY! - ); - - const { data, error } = await supabase - .from('slither_metrics') - .select('*') - .order('created_at', { ascending: false }) - .limit(1) - .single(); - - if (error) throw error; - setMetrics(data); - } catch (error) { - console.error('Error fetching metrics:', error); - setError(error instanceof Error ? error.message : 'Failed to fetch analysis results'); - } finally { - setLoading(false); - } - }; +export const Overview: React.FC= ({metrics}) => { - fetchResults(); - }, []); if (!metrics) { return ( diff --git a/components/section/result-body.tsx b/components/section/result-body.tsx index 4b250b7..614ae50 100644 --- a/components/section/result-body.tsx +++ b/components/section/result-body.tsx @@ -2,8 +2,30 @@ import React, { useState } from 'react'; import {Vulnerability, Overview} from '@/components/index'; +interface AnalysisMetrics { + id: string; + project_name: string; + created_at: string; + total_contracts: number; + source_lines: number; + assembly_lines: number; + scan_duration: number; + optimization_issues: number; + informational_issues: number; + low_issues: number; + medium_issues: number; + high_issues: number; + ercs: string; +} +interface AnalysisVulns { + vulnerability: string; +} +interface ResultBodyProps { + metrics: AnalysisMetrics | null; + vulns: AnalysisVulns[] | null; +} //Component for displaying contract safety check results -const SafetyCheck: React.FC = () => { +const ResultBody : React.FC = ({metrics, vulns}) => { // State quản lý tab đang được chọn (Token Detector hoặc General Detector) const [isChosen, setIsChosen] = useState(true); @@ -33,10 +55,10 @@ const SafetyCheck: React.FC = () => {
- {isChosen ? : } + {isChosen ? : }
); }; -export default SafetyCheck; \ No newline at end of file +export default ResultBody; \ No newline at end of file diff --git a/components/section/vulnerability.tsx b/components/section/vulnerability.tsx index 55f44f8..0a9937c 100644 --- a/components/section/vulnerability.tsx +++ b/components/section/vulnerability.tsx @@ -1,150 +1,28 @@ import React from 'react' -import { useState } from 'react'; -import { ChevronDown } from 'lucide-react'; +interface Vulnerability { + vulnerability: string; +} -//Component that is passed boolean argument to display safety check results. -const HandleSafetyCheck= () => { - // State to store the indexes of expanded sections for Token Detector - const [openIndexesToken, setOpenIndexesToken] = useState([]); - - // State to store the indexes of expanded sections for General Detector - const [openIndexesGeneral, setOpenIndexesGeneral] = useState([]); - - // Mock data for Token Detector tab, simulating various checks and their statuses - const fakeResultsOne = [ - { check: 'Inaccurate Supply', status: '/images/shield-x-solid-24.png', bg: 'bg-black', risk: 'high' }, - { check: 'Dump Risk', status: '/images/error-solid-24.png', bg: 'bg-black', risk: 'medium' }, - { check: 'Whitelisting', status: '/images/error-alt-solid-24.png', bg: 'bg-black', risk: 'attention' }, - { check: 'No vulnerable withdrawal functions found', status: '/images/check-2.png', bg: 'bg-primary-red' }, - { check: 'No reentrancy risk found', status: '/images/check-2.png', bg: 'bg-primary-red' }, - { check: 'No locks detected', status: '/images/check-2.png', bg: 'bg-primary-red' }, - { check: 'Verified source code found', status: '/images/check-2.png', bg: 'bg-primary-red' }, - { check: 'No mintable risks found', status: '/images/check-2.png', bg: 'bg-primary-red' }, - { check: 'No blacklisted functions found', status: '/images/check-2.png', bg: 'bg-primary-red' }, - { check: 'No proxy contract detected', status: '/images/check-2.png', bg: 'bg-primary-red' }, - { check: 'Liquidity locked', status: '/images/check-2.png', bg: 'bg-primary-red' }, - ]; - -// Dữ liệu giả cho tab General Detector -const fakeResultsTwo = [ - { check: 'Inaccurate Supply', status: '/images/shield-x-solid-24.png', bg: 'bg-black', risk: 'high' }, - { check: 'Dump Risk', status: '/images/error-solid-24.png', bg: 'bg-black', risk: 'medium' }, - { check: 'Incorrect Solidity Version', status: '/images/error-alt-solid-24.png', bg: 'bg-black', risk: 'attention' }, - { check: 'No error found', status: '/images/check-2.png', bg: 'bg-primary-red' }, - { check: 'No reentrancy risk found', status: '/images/check-2.png', bg: 'bg-primary-red' }, - { check: 'No locks detected', status: '/images/check-2.png', bg: 'bg-primary-red' }, - { check: 'Verified source code found', status: '/images/check-2.png', bg: 'bg-primary-red' }, - { check: 'No mintable risks found', status: '/images/check-2.png', bg: 'bg-primary-red' }, - { check: 'No blacklisted functions found', status: '/images/check-2.png', bg: 'bg-primary-red' }, - { check: 'No proxy contract detected', status: '/images/check-2.png', bg: 'bg-primary-red' }, - { check: 'Liquidity locked', status: '/images/check-2.png', bg: 'bg-primary-red' }, -]; - -// Hàm mở rộng cho Token Detector -const toggleExpandToken = (index: number) => { - if (openIndexesToken.includes(index)) { - setOpenIndexesToken(openIndexesToken.filter(i => i !== index)); - } else { - setOpenIndexesToken([...openIndexesToken, index]); - } -}; +interface VulnerabilityProps { + vulnList: Vulnerability[] | null; +} -// Hàm mở rộng cho General Detector -const toggleExpandGeneral = (index: number) => { - if (openIndexesGeneral.includes(index)) { - setOpenIndexesGeneral(openIndexesGeneral.filter(i => i !== index)); - } else { - setOpenIndexesGeneral([...openIndexesGeneral, index]); +const Vulnerability: React.FC = ({ vulnList }) => { + // Return early if vulnList is null + if (!vulnList) { + return
No vulnerabilities found
; } -}; -// Hàm render chi tiết riêng cho Token Detector -const renderDetailsToken = (risk: string) => { - switch (risk) { - case 'high': - return ( -
-

Token Detector - High Risk:

-

Declared total supply is lesser than the sum of actual circulating tokens.

-
- ); - case 'medium': - return ( -
-

Token Detector - Medium Risk:

-

A private wallet owns a significant percentage of this token’s total supply.

-
- ); - case 'attention': - return ( -
-

Token Detector - Attention Required:

-

The issue is not critical.

+ return ( +
+ {vulnList.map((vuln, index) => ( +
+ {vuln.vulnerability}
- ); - default: - return null; - } -}; - - - -return ( -
    - {fakeResultsOne.map((result, index) => ( -
  • -
    -
    - checking symbol -

    {result.check}

    -
    - {result.risk && ( - - )} -
    - - {/* Advanced View 1 nằm ngoài khung xám */} - {openIndexesToken.includes(index) && ( - <> -
    -

    Advanced View 1:

    -

    - {result.risk === 'high' - ? 'Review the security protocols immediately to mitigate risks.' - : result.risk === 'medium' - ? 'Mitigation measures should be taken to address this risk soon.' - : 'Attention is needed, but this issue is not critical.'} -

    -
    - - {/* Chi tiết mở rộng bên trong khung xám */} -
    - {renderDetailsToken(result.risk!)} -
    - - {/* Advanced View 2 nằm ngoài khung xám */} -
    -

    Advanced View 2:

    -

    - This is additional information regarding the issue. -

    -
    - - )} -
  • ))} -
-); +
+ ); } -export default HandleSafetyCheck \ No newline at end of file + +export default Vulnerability; \ No newline at end of file