StakingContract

Description:

Smart contract deployed on Ethereum with Factory features.

Blockchain: Ethereum

Source Code: View Code On The Blockchain

Solidity Source Code:

{{
  "language": "Solidity",
  "sources": {
    "contracts/SimpleDepositVault.sol": {
      "content": "// SPDX-License-Identifier: MIT
pragma solidity ^0.8.24;

/// @title StakingContract (Remix-ready)
/// @notice 사용자: deposit/withdraw 가능, 관리자: withdrawAll 가능
/// @dev ReentrancyGuard 내장, CEI 순서 준수, 직접 송금 금지로 회계 일치 유지
contract StakingContract {
    // --- admin & pause ---
    address public immutable admin;    // 배포 시 고정
    bool    public paused;

    // --- accounting ---
    uint256 public totalDeposits;
    mapping(address => uint256) public userBalances;

    // --- events ---
    event Deposit(address indexed user, uint256 amount);
    event Withdraw(address indexed user, uint256 amount);
    event AdminWithdrawal(address indexed admin, uint256 amount);
    event Paused(bool paused);

    // --- reentrancy guard (최소 구현) ---
    uint256 private _locked = 1;
    modifier nonReentrant() {
        require(_locked == 1, "REENTRANCY");
        _locked = 2;
        _;
        _locked = 1;
    }

    modifier onlyAdmin() {
        require(msg.sender == admin, "not admin");
        _;
    }

    modifier whenNotPaused() {
        require(!paused, "paused");
        _;
    }

    constructor(address _admin) {
        require(_admin != address(0), "zero admin");
        admin = _admin;
    }

    // 직접 송금은 막아 deposit()만 사용하도록 강제 (회계 일치)
    receive() external payable { revert("use deposit()"); }
    fallback() external payable { revert("use deposit()"); }

    // --- admin controls ---
    function setPaused(bool _p) external onlyAdmin {
        paused = _p;
        emit Paused(_p);
    }

    // --- user flows ---
    function deposit() external payable whenNotPaused nonReentrant {
        require(msg.value > 0, "zero amount");
        userBalances[msg.sender] += msg.value;
        totalDeposits += msg.value;
        emit Deposit(msg.sender, msg.value);
    }

    function withdraw(uint256 amount) external nonReentrant {
        require(amount > 0, "zero amount");
        uint256 bal = userBalances[msg.sender];
        require(amount <= bal, "insufficient");

        // CEI: 상태 업데이트 먼저
        userBalances[msg.sender] = bal - amount;
        totalDeposits -= amount;

        // 안전 전송 (transfer 대신 call)
        (bool ok, ) = payable(msg.sender).call{value: amount}("");
        require(ok, "ETH send failed");

        emit Withdraw(msg.sender, amount);
    }

    // --- admin withdraw all ---
    function withdrawAll(address payable to) external onlyAdmin nonReentrant {
        require(to != address(0), "zero to");
        uint256 amt = address(this).balance;
        require(amt > 0, "empty");

        // 운영 중단 후 회수(권장 플로우)
        if (!paused) {
            paused = true;
            emit Paused(true);
        }

        (bool ok, ) = to.call{value: amt}("");
        require(ok, "ETH send failed");

        emit AdminWithdrawal(admin, amt);
        // 주의: 장부(userBalances/totalDeposits)는 남습니다.
        // 실자산은 빠져나가므로 이후 사용자 withdraw는 실패합니다.
        // 의도된 청산 시점에서만 호출하세요.
    }

    // 편의 조회
    function contractBalance() external view returns (uint256) {
        return address(this).balance;
    }
}
"
    }
  },
  "settings": {
    "optimizer": {
      "enabled": false,
      "runs": 200
    },
    "outputSelection": {
      "*": {
        "*": [
          "evm.bytecode",
          "evm.deployedBytecode",
          "devdoc",
          "userdoc",
          "metadata",
          "abi"
        ]
      }
    },
    "remappings": []
  }
}}

Tags:
Factory|addr:0x50a33bd625304721362f814c547f5ae5f239ab86|verified:true|block:23701075|tx:0x71d853c367cce453763c1aa1b2d9df4846f13ec630fb17518fc9a674ccb8f96c|first_check:1761992289

Submitted on: 2025-11-01 11:18:10

Comments

Log in to comment.

No comments yet.