Libro blanco / Documentación Técnica FIV LATAM COIN (FIV)

Resumen Ejecutivo

FIV LATAM Coin es un token ERC-20 avanzado diseñado para potenciar una economía descentralizada y fortalecer la adopción de pagos digitales en empresas, marketplaces y plataformas comerciales.

Gracias a su integración con negocios, FIV no solo ofrece un mecanismo de inversión, sino que también brinda descuentos exclusivos, beneficios comerciales y una red sólida de aceptación, fortaleciendo su utilidad como método de pago.

Con un enfoque claro hacia la seguridad y sostenibilidad, FIV se posiciona como una herramienta fundamental en el ecosistema de inversión y tecnología blockchain de FIV LATAM, un proyecto que busca el crecimiento y desarrollo económico digital en Latinoamérica y a nivel global.

Este documento describe la arquitectura, las funcionalidades clave y las aplicaciones prácticas del token FIV, destacando su papel en la inclusión financiera y la innovación digital.

1. Equipo

– Renzo Montero: Fundador, CEO y desarrollador de software
– Brayán Montero: Director de Operaciones
– Vianni Torrealba: Marketing Director

2. Visión y Misión

🔹 Visión: Empoderar a individuos, empresas y comunidades mediante herramientas financieras descentralizadas, transparentes y seguras.

🔹 Misión: Crear un ecosistema blockchain autosostenible con incentivos reales para sus participantes, mediante un token robusto, gobernado por su comunidad y respaldado por tecnología de última generación.

3. El Problema y la Solución

Problemas actuales:

– Falta de confianza en sistemas financieros centralizados.
– Inflación y devaluación en monedas fiat.
– Limitación para acceder a inversiones de proyectos cripto
– Limitación participación democrática en decisiones de proyectos cripto.

Soluciones de FIV LATAM COIN:

– Gobernanza descentralizada, donde la comunidad vota sobre propuestas.
– Suministro de tokens controlado y transparente con vesting programado y quema automática.
– Staking con recompensas justas y sostenibles.
– Mecanismos de quema que reducen la inflación.
– Adopción en comercios y plataformas digitales que aceptarán FIV como método de pago con descuentos exclusivos.

4. Tecnología y Arquitectura del Token

FIV LATAM COIN es un token ERC-20 Upgradeable desarrollado con OpenZeppelin, con las siguientes características:
📅 Token estándar ERC-20 con actualizaciones sin perder datos.
🔹 Sistema de staking con recompensas ajustables.
🔥 Quema de tokens programada para deflación controlada.
🔐 Multisig para acciones críticas.
📈 Eventos para trazabilidad de transacciones, votaciones y recompensas.
🔠 Compatible con Ethereum, BNB Chain, Polygon, Avalanche, entre otras redes EVM.
👀 Smart Contract: Ver en BscScan

5. Economía del Token

Característica Valor
Nombre del token  FIV LATAM COIN
Símbolo FIV
Suministro inicial 100,000,000 FIV
Suministro máximo 200,000,000 FIV
Tasa de quema 0.1% por transacción (ajustable)
Tasa de recompensas 10% APR (ajustable)
Recompensas máximas 10,000,000 FIV
Función minting Controlada por el propietario
Función burning Automática y configurable
Incentivos para negocios Empresas que acepten FIV recibirán bonificaciones y descuentos

6. Gobernanza Descentralizada

FIV LATAM COIN implementa un sistema de gobernanza DAO-like, donde los holders del token pueden:
🔹 Crear propuestas sobre cambios en el ecosistema.
🔹 Votar a favor o en contra de mejoras en tasas y funcionalidades.
🔹 Ejecutar propuestas aceptadas por mayoría.
🔹 Vetarlas mediante un sistema multisig si representan riesgo para la comunidad.

🔹 Proceso:
1️⃣ El propietario crea una propuesta con descripción y duración.
2️⃣ Los holders votan (una dirección = un voto).
3️⃣ Si se alcanza mayoría antes del vencimiento, se ejecuta.
4️⃣ Si el multisig (aprobadores) alcanza el quórum de firmas, pueden vetarla.

7. Sistema de Staking y Recompensas

🔹 Los holders pueden bloquear sus tokens para participar en el staking.
🔹 Las recompensas se calculan por tiempo de staking y monto bloqueado.
🔹 Límite total de recompensas: 10M FIV.
🔹 Tasa de recompensa predeterminada: 10% APR (ajustable por el owner).
🔹 Penalizaciones por retiro temprano:

Antes de 24h: bloqueo completo.
Antes de 7 días: penalización del 10%, enviada a treasuryWallet para posible redistribución.

8. Mecanismo de Quema

🔥 Cada transferencia incluye una quema automática de tokens:
🔹 Por defecto: 0.1% del monto transferido (ajustable por el owner).
🔹 El burnRate puede configurarse dinámicamente, con un límite máximo del 5% del supply total.
🔹 Exclusión de quema para ciertas direcciones (exchanges, contratos estratégicos, partners).
🔹 Modelo deflacionario controlado, reduciendo gradualmente la oferta con el tiempo.

9. Seguridad y Multi-Sig

🔐 Medidas integradas:
🔹 Contrato auditado con OpenZeppelin.
🔹 Sistema de veto multisig (requiere quórum de firmas).
🔹 Verificación de límites de minting y recompensas.
🔹 Protección contra ataques de reentrada (ReentrancyGuard).

10. Roadmap del Proyecto

Fase Objetivos
Q1 2025 🔹 Desarrollo del contrato inteligente
🔹 Despliegue en testnet
🔹 Revisión técnica

Q2 2025 🔄 Auditoría externa
🚀 Despliegue en mainnet
🌐 Sitio web oficial y whitepaper

Q3 2025 📢 Campañas de marketing
🧹 Integración con exchanges DEX
💬 Comunidad y votaciones

Q4 2025 🛠️ Gobernanza activa y primeras propuestas
📈 Listado en CoinMarketCap y CoinGecko

Q1 2026 🧱 Implementación de casos de uso reales (pagos, marketplace)
🤝 Alianzas estratégicas

11. Conclusiones

FIV LATAM COIN es más que un token: es una herramienta poderosa para la construcción de un sistema financiero descentralizado, justo y transparente. Con una arquitectura sólida, mecanismos deflacionarios, recompensas e incentivos claros, y una gobernanza participativa, FIV busca liderar el cambio hacia una nueva economía digital en América Latina y el mundo.

12. Anexos técnicos

Lenguaje: Solidity 0.8.18

Bibliotecas usadas: OpenZeppelin (ERC20, Ownable, Upgradeable)

Interfaz compatible: ERC20, IERC20Metadata

Eventos definidos: Eventos definidos: ProposalCreated, ProposalExecuted, Staked, Unstaked, RewardClaimed, BurnExemptionSet, TokensReleased, TreasuryWalletUpdated

📄 Ver el código completo del Smart Contract

// SPDX-License-Identifier: MIT
/**
 * @title FIV LATAM Coin (FIV)
 * @dev ERC20 smart contract with extended functionality, designed for the FIV LATAM ecosystem.
 *
 * Features:
 * - 🔥 Automatic burn mechanism (configurable rate, with exemptions)
 * - 🎁 Staking system with reward distribution and early withdrawal penalties
 * - ⛓️ Annual token vesting with scheduled releases for the treasury wallet
 * - 👥 Multi-signature approval system for critical actions
 * - ⏸️ Emergency pause and unpause capabilities
 * - 🛡️ UUPS upgradeable proxy support
 *
 * Key Parameters:
 * - Initial supply: 100,000,000 FIV
 * - Maximum supply: 200,000,000 FIV
 * - Maximum burn rate: 5‰ (0.5%)
 * - Reward pool limit: 10,000,000 FIV
 * - Maximum staking reward rate: 20%
 *
 * Additional Functionality:
 * - Rewards can be claimed once every 24 hours
 * - 10% penalty on early unstaking (before 7 days)
 * - Manual and automatic burn logic during transfers
 * - Burn exemptions controllable by contract owner
 * - Vesting system uses yearly divisors for controlled token release
 * - Multisig actions require 2 approvals and expire after 7 days
 *
 * Authorization & Security:
 * - Ownable pattern used for admin control
 * - Upgrades restricted to owner via UUPS
 *
 * Developed by: Bash 1987  
 * Website: https://fivlatam.com/  
 * Year: 2025
 */

// SPDX-License-Identifier: MIT
pragma solidity ^0.8.22;

import "@openzeppelin/contracts-upgradeable/token/ERC20/ERC20Upgradeable.sol";
import "@openzeppelin/contracts-upgradeable/token/ERC20/extensions/ERC20BurnableUpgradeable.sol";
import "@openzeppelin/contracts-upgradeable/access/OwnableUpgradeable.sol";
import "@openzeppelin/contracts-upgradeable/utils/ReentrancyGuardUpgradeable.sol";
import "@openzeppelin/contracts-upgradeable/utils/PausableUpgradeable.sol";
import "@openzeppelin/contracts-upgradeable/proxy/utils/Initializable.sol";
import "@openzeppelin/contracts-upgradeable/token/ERC20/extensions/ERC20PermitUpgradeable.sol";
import "@openzeppelin/contracts-upgradeable/proxy/utils/UUPSUpgradeable.sol";

contract FIVLatamCoin is Initializable, ERC20Upgradeable, ERC20BurnableUpgradeable, OwnableUpgradeable, ReentrancyGuardUpgradeable, PausableUpgradeable, ERC20PermitUpgradeable, UUPSUpgradeable {
    // ===================== CONSTANTS =====================
    uint256 public constant INITIAL_SUPPLY = 100000000 * 10**18;
    uint256 public constant MAX_SUPPLY = 200000000 * 10**18;
    uint256 public constant MAX_BURN_RATE = 5; // in ‰ (5%)
    uint256 public constant MAX_REWARD_RATE = 20;
    uint256 public constant REWARD_SUPPLY_LIMIT = 10000000 * 10**18;
    uint256 public constant MULTISIG_REQUIRED_APPROVALS = 2;
    uint256 public constant RELEASE_INTERVAL = 365 days;
    uint256 public constant MIN_STAKE_DURATION = 1 days; 
    uint256 public constant EARLY_UNSTAKE_DURATION = 7 days; 
    uint256 public constant EARLY_UNSTAKE_PENALTY_RATE = 10; 
    uint256 public constant INTERVALO_RECLAMO = 1 days; 
    uint256 public constant ACTION_EXPIRATION = 7 days; 

    // ===================== CONFIGURABLE VARIABLES =====================
    uint256 public rewardRate;
    uint256 public burnRate; // in ‰, 1 = 0.1%
    uint256[] private releaseDivisors = [1, 2, 4, 8, 16, 32, 64, 128];

    // ===================== STAKING STATE =====================
    struct StakerInfo {
        uint256 amount;
        uint256 stakedAt;
        uint256 lastClaimed;
    }

    mapping(address => StakerInfo) public stakers;
    uint256 public totalStakedTokens;
    uint256 public rewardDistributed;
    uint256 public totalBurned;

    // ===================== MULTISIG =====================
    mapping(address => bool) public isMultiSigApprover;
    mapping(address => uint256) private approverIndex;
    address[] private approversList;
    mapping(bytes32 => mapping(address => bool)) public approvals;
    mapping(bytes32 => uint256) public approvalCounts;
    mapping(bytes32 => uint256) public actionTimestamps; 

    // ===================== BURN EXCLUSIONS =====================
    mapping(address => bool) public exemptFromBurn;

    // ===================== TOKEN VESTING =====================
    address public treasuryWallet;
    uint256 public vestingStart;
    uint256 public lastReleaseTime;
    uint256 public currentYear;

    // ===================== EVENTS =====================
    event Staked(address indexed user, uint256 amount);
    event Unstaked(address indexed user, uint256 amount, bool penalized);
    event RewardClaimed(address indexed user, uint256 amount);
    event RewardPoolDepleted();
    event TokensBurned(address indexed from, uint256 amount);
    event ApproverAdded(address indexed approver);
    event ApproverRemoved(address indexed approver);
    event ActionApproved(address indexed approver, bytes32 indexed actionId);
    event BurnExemptionSet(address indexed account, bool isExempt, address indexed setter, uint256 timestamp);
    event TokensReleased(uint256 year, uint256 amount);
    event TreasuryWalletUpdated(address indexed newWallet);
    event TasaRecompensaActualizada(uint256 newRate);
    event TasaBurnActualizada(uint256 newRate);
    event RewardRateUpdated(uint256 newRate);
    event BurnRateUpdated(uint256 newRate);
    event EmergencyWithdrawal(address indexed user, uint256 amount);



    // ===================== INITIALIZATION =====================
    function initialize(address _treasuryWallet) public initializer {
    require(_treasuryWallet != address(0), "Invalid treasury wallet");

        __ERC20_init("FIV LATAM COIN", "FIV");
        __ERC20Burnable_init();
        __Ownable_init(msg.sender);
        __ReentrancyGuard_init();
        __Pausable_init();
        __ERC20Permit_init("FIV LATAM COIN");
        __UUPSUpgradeable_init();

        _mint(msg.sender, INITIAL_SUPPLY);
        rewardRate = 5;
        burnRate = 1;
        treasuryWallet = _treasuryWallet;
        vestingStart = block.timestamp;
        lastReleaseTime = block.timestamp;
        currentYear = 0;
    }

    /// @notice Authorizes contract upgrade, limited to owner
    function _authorizeUpgrade(address newImplementation) internal override onlyOwner {}

    // ===================== TRANSFER & BURN =====================
    function customTransfer(address sender, address recipient, uint256 amount) internal {
        require(sender != address(0), "Transfer from zero address not allowed");
        require(recipient != address(0), "Transfer to zero address not allowed");

        uint256 transferAmount = amount;

        if (!exemptFromBurn[sender] && burnRate > 0 && totalBurned < (MAX_SUPPLY * MAX_BURN_RATE / 100)) {
            uint256 burnAmount = (amount * burnRate) / 1000;
            uint256 maxBurnRemaining = (MAX_SUPPLY * MAX_BURN_RATE / 100) - totalBurned;

            if (burnAmount > maxBurnRemaining) {
                burnAmount = maxBurnRemaining;
            }

            transferAmount = amount - burnAmount;
            super._burn(sender, burnAmount);
            totalBurned += burnAmount;
            emit TokensBurned(sender, burnAmount);
        }

        super._transfer(sender, recipient, transferAmount);
    }

    // ===================== STAKING =====================
    function stake(uint256 amount) external whenNotPaused nonReentrant {
        require(balanceOf(msg.sender) >= amount, "Insufficient balance to stake");
        _burn(msg.sender, amount);
        StakerInfo storage user = stakers[msg.sender];
        user.amount += amount;
        user.stakedAt = block.timestamp;
        user.lastClaimed = block.timestamp;
        totalStakedTokens += amount;
        emit Staked(msg.sender, amount);
    }

    /// @notice Allows users to withdraw staked tokens without rewards or penalties during emergencies (when paused)
    function emergencyUnstake() external whenPaused nonReentrant {
        StakerInfo storage user = stakers[msg.sender];
        require(user.amount > 0, "No staked tokens to withdraw");

        uint256 amount = user.amount;
        user.amount = 0;
        totalStakedTokens -= amount;

        _mint(msg.sender, amount); // Return tokens without rewards or penalties
        emit EmergencyWithdrawal(msg.sender, amount);
    }

    function unstake(uint256 amount) external whenNotPaused nonReentrant {
        StakerInfo storage user = stakers[msg.sender];
        require(user.amount >= amount, "Not enough staked tokens");

        bool penalized = false;
        uint256 originalAmount = amount;

        if (block.timestamp < user.stakedAt + MIN_STAKE_DURATION) {
            revert("Staking must be held for at least 24 hours");
        } else if (block.timestamp < user.stakedAt + EARLY_UNSTAKE_DURATION) {
            uint256 penaltyAmount = (amount * EARLY_UNSTAKE_PENALTY_RATE) / 100;
            amount = amount - penaltyAmount;
            penalized = true;
            _mint(treasuryWallet, penaltyAmount);
        }

        user.amount -= originalAmount;
        totalStakedTokens -= originalAmount;
        _mint(msg.sender, amount);

        emit Unstaked(msg.sender, originalAmount, penalized);
    }

    function claimReward() external whenNotPaused nonReentrant {
        require(rewardRate <= MAX_REWARD_RATE, "Reward rate exceeds allowed limit");
        StakerInfo storage user = stakers[msg.sender];
        require(user.amount > 0, "No tokens staked");
        require(block.timestamp >= user.lastClaimed + INTERVALO_RECLAMO, "Reward can be claimed only once every 24h");

        uint256 reward = (user.amount * rewardRate) / 100;
        require(rewardDistributed + reward <= REWARD_SUPPLY_LIMIT, "Reward pool exhausted");

        user.lastClaimed = block.timestamp;
        rewardDistributed += reward;
        _mint(msg.sender, reward);
        emit RewardClaimed(msg.sender, reward);
    }

    // ===================== VIEW FUNCTIONS =====================
    function getRewardAmount(address userAddress) external view returns (uint256) {
        StakerInfo storage user = stakers[userAddress];

        if (
            user.amount == 0 ||
            block.timestamp < user.lastClaimed + 1 days ||
            rewardRate > MAX_REWARD_RATE ||
            rewardDistributed >= REWARD_SUPPLY_LIMIT
        ) {
            return 0;
        }

        uint256 reward = (user.amount * rewardRate) / 100;
        uint256 remainingReward = REWARD_SUPPLY_LIMIT - rewardDistributed;

        if (reward > remainingReward) {
            return remainingReward;
        }

        return reward;
    }

    function getStakeAmount(address userAddress) external view returns (uint256) {
        return stakers[userAddress].amount;
    }

    // ===================== MULTISIG =====================
    function addApprover(address approver) external onlyOwner {
        require(!isMultiSigApprover[approver], "Already an approver");
        isMultiSigApprover[approver] = true;
        approverIndex[approver] = approversList.length;
        approversList.push(approver);
        emit ApproverAdded(approver);
    }

    function removeApprover(address approver) external onlyOwner {
        require(isMultiSigApprover[approver], "Not an approver");
        require(approversList.length > MULTISIG_REQUIRED_APPROVALS, "Cannot leave less than required approvers");

        uint256 index = approverIndex[approver];
        address lastApprover = approversList[approversList.length - 1];
        approversList[index] = lastApprover;
        approverIndex[lastApprover] = index;
        approversList.pop();
        delete approverIndex[approver];
        delete isMultiSigApprover[approver];

        emit ApproverRemoved(approver);
    }

    function approveAction(bytes32 actionId) external {
        require(isMultiSigApprover[msg.sender], "Not an authorized approver");

        // Registrar tiempo si es la primera vez
        if (approvalCounts[actionId] == 0) {
            actionTimestamps[actionId] = block.timestamp;
        }

        // Verificar expiración
        require(block.timestamp <= actionTimestamps[actionId] + ACTION_EXPIRATION, "Action expired");

        require(!approvals[actionId][msg.sender], "Already approved");

        approvals[actionId][msg.sender] = true;
        approvalCounts[actionId]++;
        emit ActionApproved(msg.sender, actionId);
    }

    function batchApproveActions(bytes32[] calldata actionIds) external {
        require(isMultiSigApprover[msg.sender], "Not an authorized approver");
        require(actionIds.length <= 20, "Too many actions in batch"); // 

        for (uint256 i = 0; i < actionIds.length; i++) {
            bytes32 actionId = actionIds[i];

            if (approvalCounts[actionId] == 0) {
                actionTimestamps[actionId] = block.timestamp;
            }

            if (!approvals[actionId][msg.sender] && block.timestamp <= actionTimestamps[actionId] + ACTION_EXPIRATION) {
                approvals[actionId][msg.sender] = true;
                approvalCounts[actionId]++;
                emit ActionApproved(msg.sender, actionId);
            }
        }
    }

    // ===================== TOKEN RELEASE =====================
    function releaseScheduledTokens() external onlyOwner {
        require(block.timestamp >= lastReleaseTime + RELEASE_INTERVAL, "Not time to release yet");
        require(currentYear < 20, "Vesting completed");
        require(currentYear < releaseDivisors.length, "Invalid release year");

        uint256 amount = 10000000 * 10**18 / releaseDivisors[currentYear];
        require(totalSupply() + amount <= MAX_SUPPLY, "Exceeds max supply");

        _mint(treasuryWallet, amount);
        lastReleaseTime = block.timestamp;
        currentYear++;
        emit TokensReleased(currentYear, amount);
    }

    // ===================== OWNER FUNCTIONS =====================
    function setTreasuryWallet(address newWallet) external onlyOwner {
        treasuryWallet = newWallet;
        emit TreasuryWalletUpdated(newWallet);
    }

    function setRewardRate(uint256 newRate) external onlyOwner {
        require(newRate > 0 && newRate <= MAX_REWARD_RATE, "Invalid reward rate");
        rewardRate = newRate;
    }

    function setBurnRate(uint256 newRate) external onlyOwner {
       require(newRate > 1 && newRate <= MAX_BURN_RATE, "Invalid burn rate");
       burnRate = newRate;
    }

    function setExemptFromBurn(address account, bool isExempt) external onlyOwner {
        exemptFromBurn[account] = isExempt;
        emit BurnExemptionSet(account, isExempt, msg.sender, block.timestamp);
    }

    function pause() external onlyOwner {
        _pause();
    }

    function unpause() external onlyOwner {
        _unpause();
    }

    // ===================== UPGRADE GAP =====================
    uint256[49] private __gap;
    }

  

Un universo de oportunidades. A tu alcance.

X