Как вызывается конструктор у этого смартконтракта?

Я участвовал в IDO, заклеймил свои монеты, используя этот смартконтрат https://bscscan.com/address/0x4e62210aacc9a979e9f20e8d14bc01b01365dc32#code

Я не понимаю, как вызывается конструктор, откуда. Такое чувство, что можно на JavaScript(или на чём-то другом) вызвать контракт и передать аргументы в конструктор. Если это так, то получается, первым аргументом можно передать абсолютной любой токен. В коде нету проверки, что IERC20 token это именна эта монета, а не какая-то другая
Вот смартконтракт этой монеты, если что:
https://bscscan.com/address/0x9767203e89dcD34851240B3919d4900d3E5069f1#code

// SPDX-License-Identifier: MIT

pragma solidity ^0.8.0;

import "Ownable.sol";
import "IERC20.sol";
import "ERC20.sol";
import {SafeERC20} from "SafeERC20.sol";
import {SafeMath} from "SafeMath.sol";

contract A4Sale is Ownable  {

    using SafeERC20 for IERC20;
    using SafeMath for uint256;

    IERC20 private _token;
    IERC20 private _currency;

    uint256 public _cap;
    uint256 private _rate = 1;

    uint256 public startTime;
    uint256 public releaseTime;
    uint256 public claimTime;
    uint256 public endTime;

    uint256 private minDepositValue = 10 * 10 ** 18;
    uint256 private minWithdrawValue = 1 * 10 ** 18;
    uint256 private _unitsTotal = 0;

    mapping(address => uint256) public _deposits;

    event Deposit(address indexed, uint256 indexed, uint256 indexed);
    event Withdraw(address indexed, uint256 indexed, uint256 indexed);
    event TokenWithdrowed(address indexed, uint256 indexed);


    constructor(
        IERC20 token,
        IERC20 currency,
        uint256 cap,
        uint256 _startTime,
        uint256 _releaseTime,
        uint256 _claimTime,
        uint256 _endTime ) public
    {
        _token = token;
        _currency = currency;
        _cap = cap;

        startTime = _startTime;
        releaseTime = _releaseTime;
        claimTime = _claimTime;
        endTime = _endTime;
    }

    function rate() view public returns (uint256) {
        return _rate;
    }

    function total() view public returns (uint256) {
        return _unitsTotal;
    }

    // investor token balance 
    function balanceOf(address investor) view public returns (uint256) {
        return _deposits[investor];
    }

    function deposit( uint256 value ) public {
        _deposit(value);
    }

    function withdraw( uint256 value ) public {
        _withdraw(value);
    }

    function withdrawTokens() public {
        _withdrawTokens();
    }

    function withdrawIDO( uint256 value ) onlyOwner public {
        require(claimTime <= block.timestamp, "IDO is active");
        
        _unitsTotal = _unitsTotal.sub(value);
        IERC20(_currency).transfer(msg.sender, value);
    }

    function _deposit( uint256 value ) internal
    {
        require(startTime <= block.timestamp &&  releaseTime > block.timestamp, "IDO is stopped");
        require(value >= minDepositValue, "Not enough value");

        _deposits[msg.sender] = _deposits[msg.sender].add(value);
        _unitsTotal = _unitsTotal.add(value);

        _rate = _unitsTotal.div(_cap);

        IERC20(_currency).transferFrom(msg.sender, address(this), value);

        emit Deposit(msg.sender, value, _rate);
    }

    function _withdraw( uint256 value ) internal
    {
        require(releaseTime <= block.timestamp && claimTime > block.timestamp, "No time for withdraw");
        require(value <= _deposits[msg.sender] && value > minWithdrawValue, "Error withdraw value");

        _deposits[msg.sender] = _deposits[msg.sender].sub(value);
        _unitsTotal = _unitsTotal.sub(value);
        _rate = _unitsTotal.div(_cap);

        IERC20(_currency).transfer(msg.sender, value);

        emit Withdraw(msg.sender, value, _rate);
    }

    function _withdrawTokens() internal
    {
        require(claimTime <= block.timestamp && endTime > block.timestamp, "No time for claime");
        require(_deposits[msg.sender] > 0, "Zero tokens");

        uint256 tokens = _deposits[msg.sender].div(_rate);
        _deposits[msg.sender] = 0;

        _token.transfer(msg.sender, tokens);
        
        emit TokenWithdrowed(msg.sender, tokens);
    }

    
}

Ответы (1 шт):

Автор решения: Михаил Камахин

Спросил в телеге в тематической беседе. Сказали, что конструктор вызывается на этапе деплоя контракта, то есть на этапе создания контракта. Получается(предполагаю), что если я случайно на этапе создания контракта отправлю не те монеты, они успешно добавятся.

Думаю, что надо создать функцию, которая проверяет, что это нужный токен. В конструкторе можно что-то передавать, но если мы ошибёмся, надо проверять, что мы инициализируем IDO для нужного токена. Создать для инициализации IDO функцию, которая проверяется на каждой функции в смартконтракте, что используется нужная монета. Эту функцию сможет вызывать только создатель смартконтракта, причём только один раз, если это нужная монета.

В таком случае у нас будет возможность не создавать новый смартконтракт, если мы ошибёмся.

Если вы считаете, что это не так, напишите об этом. Solidity это язык, на котором тестировать код стоит денег, а мне не хочется все мои приколы тестировать деньгами :D

→ Ссылка