UPCXArbitrumBridge

Description:

ERC20 token contract with Factory capabilities. Standard implementation for fungible tokens on Ethereum.

Blockchain: Ethereum

Source Code: View Code On The Blockchain

Solidity Source Code:

{{
  "language": "Solidity",
  "sources": {
    "@openzeppelin/contracts/token/ERC20/IERC20.sol": {
      "content": "// SPDX-License-Identifier: MIT
// OpenZeppelin Contracts (last updated v5.4.0) (token/ERC20/IERC20.sol)

pragma solidity >=0.4.16;

/**
 * @dev Interface of the ERC-20 standard as defined in the ERC.
 */
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 value of tokens in existence.
     */
    function totalSupply() external view returns (uint256);

    /**
     * @dev Returns the value of tokens owned by `account`.
     */
    function balanceOf(address account) external view returns (uint256);

    /**
     * @dev Moves a `value` amount of 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 value) 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 a `value` amount of tokens 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 value) external returns (bool);

    /**
     * @dev Moves a `value` amount of tokens from `from` to `to` using the
     * allowance mechanism. `value` 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 value) external returns (bool);
}
"
    },
    "contracts/ApproverChangeRequest.sol": {
      "content": "// SPDX-License-Identifier: MIT

pragma solidity ^0.8.0;

struct ApproverChangeRequest {
    uint8 approverIndex; // 0: A, 1: B, 2: C
    address newApprover;
    bool active;
    uint256 approvalCount;
    mapping(address => bool) approvals;
}"
    },
    "contracts/OwnershipTransferRequest.sol": {
      "content": "// SPDX-License-Identifier: MIT

pragma solidity ^0.8.0;

struct OwnershipTransferRequest {
    address newOwner;
    bool active;
    uint256 approvalCount;
    mapping(address => bool) approvals;
}"
    },
    "contracts/UPCChangeRequest.sol": {
      "content": "// SPDX-License-Identifier: MIT

pragma solidity ^0.8.0;

struct UPCChangeRequest {
    address newUPCAddress;
    bool active;
    uint256 approvalCount;
    mapping(address => bool) approvals;
}"
    },
    "contracts/UPCXArbitrumBridge.sol": {
      "content": "// SPDX-License-Identifier: MIT\r
\r
pragma solidity ^0.8.0;\r
\r
import "@openzeppelin/contracts/token/ERC20/IERC20.sol";\r
import "./WithdrawRequest.sol";\r
import "./UPCChangeRequest.sol";\r
import "./OwnershipTransferRequest.sol";\r
import "./ApproverChangeRequest.sol";\r
\r
contract UPCXArbitrumBridge {\r
    address public UPC_Address;\r
    address public owner;\r
    address public approverA;\r
    address public approverB;\r
    address public approverC;\r
\r
    bool public existPendingRequest;\r
\r
    WithdrawRequest public withdrawRequest;\r
    UPCChangeRequest public upcChangeRequest;\r
    OwnershipTransferRequest public ownershipTransferRequest;\r
    ApproverChangeRequest public approverChangeRequest;\r
\r
    event WithdrawRequested(address indexed owner, address indexed to, uint256 amount);\r
    event WithdrawApproved(address indexed approver, address indexed to, uint256 amount);\r
    event WithdrawCompleted(address indexed to, uint256 amount);\r
\r
    event OwnershipTransferRequested(address indexed currentOwner, address indexed newOwner);\r
    event OwnershipTransferApproved(address indexed approver, address indexed newOwner);\r
    event OwnershipTransferred(address indexed previousOwner, address indexed newOwner);\r
\r
    event ApproverChangeRequested(address indexed owner, uint8 indexed approverIndex, address indexed newApprover);\r
    event ApproverChangeApproved(address indexed approver, uint8 indexed approverIndex, address indexed newApprover);\r
    event ApproverChanged(uint8 indexed approverIndex, address indexed newApprover);\r
\r
    event Convert(address indexed user, uint256 indexed amount);\r
\r
    modifier onlyOwner() {\r
        require(msg.sender == owner, "Not the owner");\r
        _;\r
    }\r
\r
    modifier onlyApprovers() {\r
        require(\r
            msg.sender == approverA || msg.sender == approverB || msg.sender == approverC,\r
            "Not an approver"\r
        );\r
        _;\r
    }\r
\r
    modifier onlyApproversOrPending() {\r
        bool isApprover = (msg.sender == approverA || msg.sender == approverB || msg.sender == approverC);\r
        bool isPending = false;\r
        if (approverChangeRequest.active) {\r
            if (approverChangeRequest.approverIndex == 0) {\r
                // ApproverA is being replaced, so only approverB, approverC, and newApprover can approve\r
                isApprover = (msg.sender == approverB || msg.sender == approverC);\r
                isPending = (msg.sender == approverChangeRequest.newApprover);\r
            } else if (approverChangeRequest.approverIndex == 1) {\r
                // ApproverB is being replaced, so only approverA, approverC, and newApprover can approve\r
                isApprover = (msg.sender == approverA || msg.sender == approverC);\r
                isPending = (msg.sender == approverChangeRequest.newApprover);\r
            } else if (approverChangeRequest.approverIndex == 2) {\r
                // ApproverC is being replaced, so only approverA, approverB, and newApprover can approve\r
                isApprover = (msg.sender == approverA || msg.sender == approverB);\r
                isPending = (msg.sender == approverChangeRequest.newApprover);\r
            }\r
        }\r
        require(isApprover || isPending, "Not an approver or pending approver");\r
        _;\r
    }\r
\r
    constructor(address _upcAddress, address _approverA, address _approverB, address _approverC)  {\r
        UPC_Address = _upcAddress;\r
        owner = msg.sender;\r
        approverA = _approverA;\r
        approverB = _approverB;\r
        approverC = _approverC;\r
    }\r
\r
    // Owner registers a request to change UPC address\r
    function requestUPCAddressChange(address _newUPCAddress) external onlyOwner {\r
        require(_newUPCAddress != address(0), "Invalid address");\r
        require(!existPendingRequest, "Another request is pending");\r
        upcChangeRequest.newUPCAddress = _newUPCAddress;\r
        upcChangeRequest.active = true;\r
        upcChangeRequest.approvalCount = 0;\r
        upcChangeRequest.approvals[approverA] = false;\r
        upcChangeRequest.approvals[approverB] = false;\r
        upcChangeRequest.approvals[approverC] = false;\r
        existPendingRequest = true;\r
    }\r
\r
    // Approvers approve the pending UPC address change\r
    function approveUPCAddressChange() external onlyApprovers {\r
        require(upcChangeRequest.active, "No pending request");\r
        require(!upcChangeRequest.approvals[msg.sender], "Already approved");\r
        upcChangeRequest.approvals[msg.sender] = true;\r
        upcChangeRequest.approvalCount++;\r
        if (upcChangeRequest.approvalCount >= 2) {\r
            UPC_Address = upcChangeRequest.newUPCAddress;\r
            // Reset\r
            upcChangeRequest.active = false;\r
            upcChangeRequest.newUPCAddress = address(0);\r
            upcChangeRequest.approvalCount = 0;\r
            upcChangeRequest.approvals[approverA] = false;\r
            upcChangeRequest.approvals[approverB] = false;\r
            upcChangeRequest.approvals[approverC] = false;\r
            existPendingRequest = false;\r
        }\r
    }\r
\r
    // Owner registers a withdraw request\r
    function requestWithdraw(address to, uint256 amount) external onlyOwner {\r
        require(!existPendingRequest, "Another request is pending");\r
        require(amount > 0, "Amount must be > 0");\r
        withdrawRequest.amount = amount;\r
        withdrawRequest.to = to;\r
        withdrawRequest.active = true;\r
        withdrawRequest.approvalCount = 0;\r
        withdrawRequest.approvals[approverA] = false;\r
        withdrawRequest.approvals[approverB] = false;\r
        withdrawRequest.approvals[approverC] = false;\r
        existPendingRequest = true;\r
        emit WithdrawRequested(msg.sender, to, amount);\r
    }\r
\r
    // Approvers approve the withdraw request\r
    function approveWithdraw() external onlyApprovers {\r
        require(withdrawRequest.active, "No active withdraw request");\r
        require(!withdrawRequest.approvals[msg.sender], "Already approved");\r
        withdrawRequest.approvals[msg.sender] = true;\r
        withdrawRequest.approvalCount++;\r
        emit WithdrawApproved(msg.sender, withdrawRequest.to, withdrawRequest.amount);\r
        if (withdrawRequest.approvalCount >= 2) {\r
            require(IERC20(UPC_Address).transfer(withdrawRequest.to, withdrawRequest.amount), "Transfer failed");\r
            emit WithdrawCompleted(withdrawRequest.to, withdrawRequest.amount);\r
            // Reset\r
            withdrawRequest.active = false;\r
            withdrawRequest.amount = 0;\r
            withdrawRequest.to = address(0);\r
            withdrawRequest.approvalCount = 0;\r
            withdrawRequest.approvals[approverA] = false;\r
            withdrawRequest.approvals[approverB] = false;\r
            withdrawRequest.approvals[approverC] = false;\r
            existPendingRequest = false;\r
        }\r
    }\r
\r
    function convert(uint256 amount) external {\r
        require(IERC20(UPC_Address).allowance(msg.sender, address(this)) >= amount, "Insufficient allowance");\r
        require(IERC20(UPC_Address).transferFrom(msg.sender, address(this), amount), "Transfer failed");\r
\r
        emit Convert(msg.sender, amount);\r
    }\r
\r
    // Owner registers a request to transfer ownership\r
    function requestOwnershipTransfer(address _newOwner) external onlyOwner {\r
        require(_newOwner != address(0), "Invalid address");\r
        require(!existPendingRequest, "Another request is pending");\r
        ownershipTransferRequest.newOwner = _newOwner;\r
        ownershipTransferRequest.active = true;\r
        ownershipTransferRequest.approvalCount = 0;\r
        ownershipTransferRequest.approvals[approverA] = false;\r
        ownershipTransferRequest.approvals[approverB] = false;\r
        ownershipTransferRequest.approvals[approverC] = false;\r
        existPendingRequest = true;\r
        emit OwnershipTransferRequested(owner, _newOwner);\r
    }\r
\r
    // Approvers approve the ownership transfer request\r
    function approveOwnershipTransfer() external onlyApprovers {\r
        require(ownershipTransferRequest.active, "No active transfer request");\r
        require(!ownershipTransferRequest.approvals[msg.sender], "Already approved");\r
        ownershipTransferRequest.approvals[msg.sender] = true;\r
        ownershipTransferRequest.approvalCount++;\r
        emit OwnershipTransferApproved(msg.sender, ownershipTransferRequest.newOwner);\r
        if (ownershipTransferRequest.approvalCount >= 2) {\r
            address previousOwner = owner;\r
            owner = ownershipTransferRequest.newOwner;\r
            emit OwnershipTransferred(previousOwner, owner);\r
            // Reset\r
            ownershipTransferRequest.active = false;\r
            ownershipTransferRequest.newOwner = address(0);\r
            ownershipTransferRequest.approvalCount = 0;\r
            ownershipTransferRequest.approvals[approverA] = false;\r
            ownershipTransferRequest.approvals[approverB] = false;\r
            ownershipTransferRequest.approvals[approverC] = false;\r
            existPendingRequest = false;\r
        }\r
    }\r
\r
    // Owner registers a request to change an approver address\r
    function requestApproverChange(uint8 approverIndex, address newApprover) external onlyOwner {\r
        require(!existPendingRequest, "Another request is pending");\r
        require(newApprover != address(0), "Invalid address");\r
        require(approverIndex < 3, "Invalid approver index");\r
        approverChangeRequest.approverIndex = approverIndex;\r
        approverChangeRequest.newApprover = newApprover;\r
        approverChangeRequest.active = true;\r
        approverChangeRequest.approvalCount = 0;\r
        approverChangeRequest.approvals[approverA] = false;\r
        approverChangeRequest.approvals[approverB] = false;\r
        approverChangeRequest.approvals[approverC] = false;\r
        existPendingRequest = true;\r
        emit ApproverChangeRequested(msg.sender, approverIndex, newApprover);\r
    }\r
\r
    // Approvers approve the approver change request\r
    function approveApproverChange() external onlyApproversOrPending {\r
        require(approverChangeRequest.active, "No active approver change request");\r
        require(!approverChangeRequest.approvals[msg.sender], "Already approved");\r
        approverChangeRequest.approvals[msg.sender] = true;\r
        approverChangeRequest.approvalCount++;\r
        emit ApproverChangeApproved(msg.sender, approverChangeRequest.approverIndex, approverChangeRequest.newApprover);\r
        if (approverChangeRequest.approvalCount >= 2) {\r
            if (approverChangeRequest.approverIndex == 0) {\r
                approverA = approverChangeRequest.newApprover;\r
            } else if (approverChangeRequest.approverIndex == 1) {\r
                approverB = approverChangeRequest.newApprover;\r
            } else if (approverChangeRequest.approverIndex == 2) {\r
                approverC = approverChangeRequest.newApprover;\r
            }\r
            emit ApproverChanged(approverChangeRequest.approverIndex, approverChangeRequest.newApprover);\r
            // Reset\r
            approverChangeRequest.active = false;\r
            approverChangeRequest.newApprover = address(0);\r
            approverChangeRequest.approverIndex = 0;\r
            approverChangeRequest.approvalCount = 0;\r
            approverChangeRequest.approvals[approverA] = false;\r
            approverChangeRequest.approvals[approverB] = false;\r
            approverChangeRequest.approvals[approverC] = false;\r
            existPendingRequest = false;\r
        }\r
    }\r
}\r
\r
"
    },
    "contracts/WithdrawRequest.sol": {
      "content": "// SPDX-License-Identifier: MIT

pragma solidity ^0.8.0;

struct WithdrawRequest {
    uint256 amount;
    address to;
    bool active;
    uint256 approvalCount;
    mapping(address => bool) approvals;
}"
    }
  },
  "settings": {
    "evmVersion": "paris",
    "optimizer": {
      "enabled": false,
      "runs": 200
    },
    "outputSelection": {
      "*": {
        "*": [
          "evm.bytecode",
          "evm.deployedBytecode",
          "devdoc",
          "userdoc",
          "metadata",
          "abi"
        ]
      }
    }
  }
}}

Tags:
ERC20, Token, Factory|addr:0xb948dbf3f9f77b903823e35a6ec7a75e441000ad|verified:true|block:23581577|tx:0x8a272ff426647dd40824384b103fa8620d7da6cd545270418993d7fd5aa3d36f|first_check:1760520573

Submitted on: 2025-10-15 11:29:34

Comments

Log in to comment.

No comments yet.