¿Cómo permitir que solo el propietario transfiera tokens ERC20 durante la venta masiva?

Recientemente me encontré con una ICO que usaba billeteras temporales. Los tokens se enviaron a los inversores manualmente, lo que significa que no todos recibieron sus tokens al mismo tiempo. Hasta que todos recibieran sus tokens, estaban bloqueados para transferencias. Sin embargo, el propietario pudo transferir los tokens a los inversores. Con fines de aprendizaje, traté de reproducir esta lógica y me preguntaba si mi intento realmente podría usarse en términos de eficiencia y seguridad. La función transferFrom tiene la misma lógica.

Gracias por tus comentarios.

function transfer(address _to, uint256 _value) public returns (bool success) {
    require(
        balances[msg.sender] >= _value
        && _value > 0
    );
    if(locked == true){
        if(msg.sender == owner){
            balances[msg.sender] = balances[msg.sender].sub(_value);
            balances[_to] = balances[_to].add(_value);
            emit Transfer(msg.sender, _to, _value);
            return true;
        }else{
            revert();
        }
    }else{
        balances[msg.sender] = balances[msg.sender].sub(_value);
        balances[_to] = balances[_to].add(_value);
        emit Transfer(msg.sender, _to, _value);
        return true;
    }
}

Respuestas (2)

Para evitar repetir la lógica:

function transfer(address _to, uint256 _value) public returns (bool success) {
    require(balances[msg.sender] >= _value);

    require(!locked || (msg.sender == owner));

    balances[msg.sender] = balances[msg.sender].sub(_value);
    balances[_to] = balances[_to].add(_value);
    emit Transfer(msg.sender, _to, _value);
    return true;
}

(Descarté el requisito _value >= 0porque ERC20 en realidad espera que las transferencias de 0 tengan éxito).

Una alternativa es usar una lista blanca y un modificador

mapping (address => bool) allowTransfer;

modifier canTransfer(address user) {
    require(!locked || allowTransfer[user]);
    _;
}

function enableTransfer(address user, bool enable) onlyOwner {
    allowTransfer[user] = enable;
}

Y hay que modificar ligeramente la función de transferencia.

function transfer(address _to, uint256 _value) 
        canTransfer(msg.sender) 
        public returns (bool success) {
    require(balances[msg.sender] >= _value);
    balances[msg.sender] = balances[msg.sender].sub(_value);
    balances[_to] = balances[_to].add(_value);
    emit Transfer(msg.sender, _to, _value);
    return true;
}

Créditos a la implementación de ReleseableToken en los repositorios de TokenMarket.