Untitled

mail@pastecode.io avatar
unknown
javascript
2 years ago
5.3 kB
3
Indexable
Never
pragma solidity ^0.8.17;
import "hardhat/console.sol";

interface IERC20 {
    event Transfer(address indexed from, address indexed to, uint256 value);
    event Approval(address indexed owner, address indexed spender, uint256 value);

    function totalSupply() external view returns (uint256);
    function balanceOf(address account) external view returns (uint256);
    function transfer(address to, 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 from, address to, uint256 amount) external returns (bool);
}


contract BridgeBase {

    // MARK: - Interfaces

    enum Step { Deposit, Transfer }

    struct BridgeDepositDeal {
        uint id;
        address from;
        address to;
        uint amount;
        uint date;
        Step step;
    }

    struct BridgeTransferMoneyDeal {
        uint id;
        address from;
        address to;
        uint amount;
        uint date;
        Step step;
        bool isFinishTransfer;
    }


    // MARK: - Variables

    address public owner;
    address public admin;
    IERC20 public token;

    BridgeDepositDeal[] public bridgeDepositDeals;
    mapping(uint => BridgeDepositDeal) public mapBridgeDepositDeals;

    BridgeTransferMoneyDeal[] public bridgeTransferMoneyDeals;
    mapping(uint => BridgeTransferMoneyDeal) public mapBridgeTransferMoneyDeals;


    // MARK: - Events

    event Deposit(
        uint id,
        address from,
        address to,
        uint amount,
        uint date,
        Step step
    );

    event TransferMoneyEvent(
        uint id,
        address to,
        uint amount,
        uint date,
        Step step
    );


    // MARK: - Constructor

    constructor(address _token, address _admin) {
        owner = msg.sender;
        admin = _admin;
        token = IERC20(_token);
    }


    // MARK: - ADMIN OR OWNER ONLY

    function withdrawMoney(address _to, uint amount) external {
        require(msg.sender == owner || msg.sender == admin, 'only owner');
        require(amount > 0, 'amount need more 0');

        uint balance = token.balanceOf(address(this));

        require(balance > amount, "amount more then balance");

        token.transfer(_to, amount);
    }

    function updateAdmin(address _admin) external {
        require(msg.sender == owner, 'only owner');
        admin = _admin;
    }

    function depositBalanceFromAdmin(uint amount) public {
        require(msg.sender == admin, 'only admin');
        bool transferSuccess = token.transfer(address(this), amount);
        require(transferSuccess, 'error transfer');
    }


    // MARK: - DEPOSIT
    // Для пополнения средств смарт контракта на первом блокчейне

    function getBridgeDepositDealCount() public view returns (uint) {
        return bridgeDepositDeals.length;
    }

    // need approve from msg sender
    // token.approve(_to, amount)
    function depositMoney(address _to, uint _amount) public {
        require(_amount > 0, 'amount need more then 0');

        bool transferSuccess = token.transferFrom(msg.sender, address(this), _amount);
        require(transferSuccess, 'error transfer');

        uint numberOfDeal = bridgeDepositDeals.length;

        BridgeDepositDeal memory bridgeDepositDeal = BridgeDepositDeal(
            numberOfDeal,
            msg.sender,
            _to,
            _amount,
            block.timestamp,
            Step.Deposit
        );

        bridgeDepositDeals.push(bridgeDepositDeal);

        mapBridgeDepositDeals[numberOfDeal] = bridgeDepositDeal;

        emit Deposit(
            numberOfDeal,
            msg.sender,
            _to,
            _amount,
            block.timestamp,
            Step.Deposit
        );
    }


    // MARK: - TRANSFER
    // Для пополнения средств со смарт контракта на втором блокчейне

    function getBridgeTransferMoneyDealCount() public view returns (uint) {
        return bridgeTransferMoneyDeals.length;
    }

    function transferMoney(address _from, address _to, uint _amount, uint _depositDealId) public {
        require(_amount > 0, 'amount need more then 0');

        uint tokenBalance = token.balanceOf(address(this));

        require(tokenBalance > _amount, 'small token count');

        require(mapBridgeTransferMoneyDeals[_depositDealId].to == address(0), 'Deal already have');

        // need calculate commission
        uint totalAmount = _amount;


        BridgeTransferMoneyDeal memory bridgeTransferMoneyDeal = BridgeTransferMoneyDeal(
            _depositDealId,
            _from,
            _to,
            totalAmount,
            block.timestamp,
            Step.Transfer,
            false
        );


        bool transferState = token.transfer(_to, totalAmount);
        require(transferState, 'error transfer money');


        bridgeTransferMoneyDeals.push(bridgeTransferMoneyDeal);

        mapBridgeTransferMoneyDeals[_depositDealId] = bridgeTransferMoneyDeal;

        mapBridgeTransferMoneyDeals[_depositDealId].isFinishTransfer = true;
    }
}