Address

Description:

Decentralized Finance (DeFi) protocol contract providing Mintable, Burnable, Swap, Factory functionality.

Blockchain: Ethereum

Source Code: View Code On The Blockchain

Solidity Source Code:

{{
  "language": "Solidity",
  "sources": {
    "contracts/LetiziaCoin.sol": {
      "content": "// SPDX-License-Identifier: GPL-3.0-or-later
pragma solidity ^0.8.30;

/// @dev ERC20 standard interface
interface IERC20 {
    function totalSupply() external view returns (uint256);
    function decimals() external view returns (uint8);
    function balanceOf(address account) external view returns (uint256);
    function transfer(address recipient, uint256 amount) external returns (bool);
    function allowance(address owner, address spender) external view returns (uint256);
    function approve(address spender, uint256 amount) external returns (bool);
    function transferFrom(address sender, address recipient, uint256 amount) external returns (bool);

    event Transfer(address indexed from, address indexed to, uint256 value);
    event Approval(address indexed owner, address indexed spender, uint256 value);
}

library Address {
    function isContract(address account) internal view returns (bool) {
        bytes32 codehash;
        bytes32 emptyHash = 0xc5d2460186f7233c927e7db2dcc703c0e500b653ca82273b7bfad8045d85a470;
        assembly { codehash := extcodehash(account) }
        return (codehash != 0x0 && codehash != emptyHash);
    }
}

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));
    }

    function safeApprove(IERC20 token, address spender, uint256 value) internal {
        require((value == 0) || (token.allowance(address(this), spender) == 0),
            "SafeERC20: approve from non-zero allowance"
        );
        _callOptionalReturn(token, abi.encodeWithSelector(token.approve.selector, spender, value));
    }

    function _callOptionalReturn(IERC20 token, bytes memory data) private {
        require(address(token).isContract(), "SafeERC20: call to non-contract");
        (bool success, bytes memory returndata) = address(token).call(data);
        require(success, "SafeERC20: low-level call failed");
        if (returndata.length > 0) {
            require(abi.decode(returndata, (bool)), "SafeERC20: operation did not succeed");
        }
    }
}

contract LetiziaCoin is IERC20 {
    using SafeERC20 for IERC20;

    string public name;
    string public symbol;
    uint8 public immutable override decimals;
    address public immutable underlying;
    bool public constant underlyingIsMinted = false;

    mapping(address => uint256) public override balanceOf;
    uint256 private _totalSupply;

    bool private _init;
    bool private _vaultOnly;
    uint public constant DELAY = 2 days;

    mapping(address => bool) public isMinter;
    address[] public minters;
    address public vault;
    address public pendingMinter;
    uint public delayMinter;
    address public pendingVault;
    uint public delayVault;

    mapping(address => mapping(address => uint256)) public override allowance;

    event LogChangeVault(address indexed oldVault, address indexed newVault, uint indexed effectiveTime);
    event LogSwapin(bytes32 indexed txhash, address indexed account, uint amount);
    event LogSwapout(address indexed account, address indexed bindaddr, uint amount);

    modifier onlyAuth() {
        require(isMinter[msg.sender], "LetiziaCoin: FORBIDDEN");
        _;
    }

    modifier onlyVault() {
        require(msg.sender == vault, "LetiziaCoin: FORBIDDEN");
        _;
    }

    constructor() {
        name = "LetiziaCoin";
        symbol = "LET";
        decimals = 18;
        underlying = address(0);
        _init = true;
        _vaultOnly = false;
        vault = msg.sender;
        // opzionale: _mint(msg.sender, 1_000_000 * 10 ** decimals);
    }

    // ============ ERC20 Standard ============

    function totalSupply() external view override returns (uint256) {
        return _totalSupply;
    }

    function approve(address spender, uint256 value) external override returns (bool) {
        allowance[msg.sender][spender] = value;
        emit Approval(msg.sender, spender, value);
        return true;
    }

    function transfer(address to, uint256 value) external override returns (bool) {
        _transfer(msg.sender, to, value);
        return true;
    }

    function transferFrom(address from, address to, uint256 value) external override returns (bool) {
        if (from != msg.sender) {
            uint256 allowed = allowance[from][msg.sender];
            if (allowed != type(uint256).max) {
                require(allowed >= value, "LetiziaCoin: transfer exceeds allowance");
                allowance[from][msg.sender] = allowed - value;
                emit Approval(from, msg.sender, allowance[from][msg.sender]);
            }
        }
        _transfer(from, to, value);
        return true;
    }

    // ============ Vault & Minter Control ============

    function owner() external view returns (address) {
        return vault;
    }

    function mpc() external view returns (address) {
        return vault;
    }

    function setVaultOnly(bool enabled) external onlyVault {
        _vaultOnly = enabled;
    }

    function initVault(address _vault) external onlyVault {
        require(_init, "LetiziaCoin: already initialized");
        _init = false;
        vault = _vault;
        isMinter[_vault] = true;
        minters.push(_vault);
    }

    function setVault(address _vault) external onlyVault {
        require(_vault != address(0), "LetiziaCoin: address(0)");
        pendingVault = _vault;
        delayVault = block.timestamp + DELAY;
    }

    function applyVault() external onlyVault {
        require(pendingVault != address(0) && block.timestamp >= delayVault, "LetiziaCoin: delay not passed");
        vault = pendingVault;
        pendingVault = address(0);
        delayVault = 0;
    }

    function setMinter(address _auth) external onlyVault {
        require(_auth != address(0), "LetiziaCoin: address(0)");
        pendingMinter = _auth;
        delayMinter = block.timestamp + DELAY;
    }

    function applyMinter() external onlyVault {
        require(pendingMinter != address(0) && block.timestamp >= delayMinter, "LetiziaCoin: delay not passed");
        isMinter[pendingMinter] = true;
        minters.push(pendingMinter);
        pendingMinter = address(0);
        delayMinter = 0;
    }

    function revokeMinter(address _auth) external onlyVault {
        isMinter[_auth] = false;
    }

    function getAllMinters() external view returns (address[] memory) {
        return minters;
    }

    function changeVault(address newVault) external onlyVault returns (bool) {
        require(newVault != address(0), "LetiziaCoin: address(0)");
        emit LogChangeVault(vault, newVault, block.timestamp);
        vault = newVault;
        pendingVault = address(0);
        delayVault = 0;
        return true;
    }

    // ============ Minting / Burning / Swaps ============

    function mint(address to, uint256 amount) external onlyAuth returns (bool) {
        _mint(to, amount);
        return true;
    }

    function burn(address from, uint256 amount) external onlyAuth returns (bool) {
        _burn(from, amount);
        return true;
    }

    function Swapin(bytes32 txhash, address account, uint256 amount) external onlyAuth returns (bool) {
        if (underlying != address(0) && IERC20(underlying).balanceOf(address(this)) >= amount) {
            IERC20(underlying).safeTransfer(account, amount);
        } else {
            _mint(account, amount);
        }
        emit LogSwapin(txhash, account, amount);
        return true;
    }

    function Swapout(uint256 amount, address bindaddr) external returns (bool) {
        require(!_vaultOnly, "LetiziaCoin: vaultOnly");
        require(bindaddr != address(0), "LetiziaCoin: address(0)");

        if (underlying != address(0) && balanceOf[msg.sender] < amount) {
            IERC20(underlying).safeTransferFrom(msg.sender, address(this), amount);
        } else {
            _burn(msg.sender, amount);
        }

        emit LogSwapout(msg.sender, bindaddr, amount);
        return true;
    }

    // ============ Deposits & Withdrawals ============

    function deposit() external returns (uint) {
        uint amount = IERC20(underlying).balanceOf(msg.sender);
        IERC20(underlying).safeTransferFrom(msg.sender, address(this), amount);
        return _deposit(amount, msg.sender);
    }

    function deposit(uint amount) external returns (uint) {
        IERC20(underlying).safeTransferFrom(msg.sender, address(this), amount);
        return _deposit(amount, msg.sender);
    }

    function deposit(uint amount, address to) external returns (uint) {
        IERC20(underlying).safeTransferFrom(msg.sender, address(this), amount);
        return _deposit(amount, to);
    }

    function depositVault(uint amount, address to) external onlyVault returns (uint) {
        return _deposit(amount, to);
    }

    function _deposit(uint amount, address to) internal returns (uint) {
        require(!underlyingIsMinted, "LetiziaCoin: underlying minted");
        require(underlying != address(0) && underlying != address(this), "LetiziaCoin: invalid underlying");
        _mint(to, amount);
        return amount;
    }

    function withdraw() external returns (uint) {
        return _withdraw(msg.sender, balanceOf[msg.sender], msg.sender);
    }

    function withdraw(uint amount) external returns (uint) {
        return _withdraw(msg.sender, amount, msg.sender);
    }

    function withdraw(uint amount, address to) external returns (uint) {
        return _withdraw(msg.sender, amount, to);
    }

    function withdrawVault(address from, uint amount, address to) external onlyVault returns (uint) {
        return _withdraw(from, amount, to);
    }

    function _withdraw(address from, uint amount, address to) internal returns (uint) {
        require(!underlyingIsMinted, "LetiziaCoin: underlying minted");
        require(underlying != address(0) && underlying != address(this), "LetiziaCoin: invalid underlying");
        _burn(from, amount);
        IERC20(underlying).safeTransfer(to, amount);
        return amount;
    }

    // ============ Internal Helpers ============

    function _transfer(address from, address to, uint256 amount) internal {
        require(to != address(0) && to != address(this), "LetiziaCoin: invalid address");
        uint256 bal = balanceOf[from];
        require(bal >= amount, "LetiziaCoin: insufficient balance");
        balanceOf[from] = bal - amount;
        balanceOf[to] += amount;
        emit Transfer(from, to, amount);
    }

    function _mint(address account, uint256 amount) internal {
        require(account != address(0), "ERC20: mint to zero");
        _totalSupply += amount;
        balanceOf[account] += amount;
        emit Transfer(address(0), account, amount);
    }

    function _burn(address account, uint256 amount) internal {
        require(account != address(0), "ERC20: burn from zero");
        uint256 bal = balanceOf[account];
        require(bal >= amount, "ERC20: burn exceeds balance");
        balanceOf[account] = bal - amount;
        _totalSupply -= amount;
        emit Transfer(account, address(0), amount);
    }
}
"
    }
  },
  "settings": {
    "optimizer": {
      "enabled": true,
      "runs": 200
    },
    "outputSelection": {
      "*": {
        "*": [
          "evm.bytecode",
          "evm.deployedBytecode",
          "devdoc",
          "userdoc",
          "metadata",
          "abi"
        ]
      }
    },
    "remappings": []
  }
}}

Tags:
ERC20, DeFi, Mintable, Burnable, Swap, Factory|addr:0xaecf27330004b88fe3b03cd49e38b25107e6e479|verified:true|block:23481622|tx:0x04e043397c57525e91d44528fdf93c5065eed95be9133e52d44b0ed94c362081|first_check:1759322189

Submitted on: 2025-10-01 14:36:29

Comments

Log in to comment.

No comments yet.