Bloqueo de tiempo y contrato inteligente de adquisición de derechos

Me gustaría crear un contrato inteligente que se encargue de bloquear y/o otorgar fondos a varios beneficiarios (ingresados ​​por el propietario del contrato inteligente). Los fondos que otorgará y bloqueará deben provenir de otro contrato inteligente simbólico. ¿Es eso posible? Mi pregunta es cómo se obtienen fondos de un contrato inteligente de token ERC20 para mi contrato inteligente de concesión/bloqueo para que luego pueda manipular los fondos de acuerdo con algunas reglas establecidas.

muchas gracias <3

Respuestas (1)

Si, puedes hacerlo. Será demasiado complicado para mostrar una implementación completa, por lo que solo supondré que conoce un contrato ERC20.

Generalmente, cuando se implementa un ERC20, el suministro inicial se "acuña" al implementador. El siguiente paso es transferir algunos tokens a un contrato de bloqueo de tiempo. El contrato de bloqueo de tiempo puede simplemente mantener saldos para direcciones específicas hasta que haya pasado un cierto tiempo o número de bloque, luego permitir que las direcciones del reclamante se retiren.

Este es un garabato realmente rápido y no probado para darle algunas ideas. Comenzando con la interfaz ERC20 de openzeppelin: https://github.com/OpenZeppelin/openzeppelin-solidity/blob/master/contracts/token/ERC20/IERC20.sol

pragma solidity ^0.4.24;

/**
 * @title ERC20 interface
 * @dev see https://github.com/ethereum/EIPs/issues/20
 */
interface IERC20 {
  function totalSupply() external view returns (uint256);

  function balanceOf(address who) external view returns (uint256);

  function allowance(address owner, address spender)
    external view returns (uint256);

  function transfer(address to, uint256 value) external returns (bool);

  function approve(address spender, uint256 value)
    external returns (bool);

  function transferFrom(address from, address to, uint256 value)
    external returns (bool);

  event Transfer(
    address indexed from,
    address indexed to,
    uint256 value
  );

  event Approval(
    address indexed owner,
    address indexed spender,
    uint256 value
  );
}

Luego, continúe con el contrato de bloqueo de tiempo, utilizando la interfaz ERC20 definida anteriormente.

Haremos cajas de seguridad numeradas. Los usuarios deben especificar el número de la caja que contiene sus fondos. Esto se descubre fácilmente mirando los registros de eventos. Las casillas numeradas significan que el contrato puede abordar fácilmente múltiples tramos para una sola dirección, con diferentes montos y plazos.

En caso de que no lo haya visto antes, la función de depósito utiliza transferFrom. Esto supone que el usuario primero firma una approveautorización de este contrato para ayudarse a sí mismo a una cierta cantidad de fondos. Eso generalmente se coordina desde el lado del cliente. Va, el cliente envía approve(addressTimeLock, uintAmount)al contrato de token, luego deposit(addressBeneficiary, uintAmount, uintDeadline)al contrato de bloqueo de tiempo.

contract TimeLock {
    IERC20 token;

    struct LockBoxStruct {
        address beneficiary;
        uint balance;
        uint releaseTime;
    }

    LockBoxStruct[] public lockBoxStructs; // This could be a mapping by address, but these numbered lockBoxes support possibility of multiple tranches per address

    event LogLockBoxDeposit(address sender, uint amount, uint releaseTime);   
    event LogLockBoxWithdrawal(address receiver, uint amount);

    constructor(address tokenContract) public {
        token = IERC20(tokenContract);
    }

    function deposit(address beneficiary, uint amount, uint releaseTime) public returns(bool success) {
        require(token.transferFrom(msg.sender, address(this), amount));
        LockBoxStruct memory l;
        l.beneficiary = beneficiary;
        l.balance = amount;
        l.releaseTime = releaseTime;
        lockBoxStructs.push(l);
        emit LogLockBoxDeposit(msg.sender, amount, releaseTime);
        return true;
    }

    function withdraw(uint lockBoxNumber) public returns(bool success) {
        LockBoxStruct storage l = lockBoxStructs[lockBoxNumber];
        require(l.beneficiary == msg.sender);
        require(l.releaseTime <= now);
        uint amount = l.balance;
        l.balance = 0;
        emit LogLockBoxWithdrawal(msg.sender, amount);
        require(token.transfer(msg.sender, amount));
        return true;
    }    

}

No existe la noción de una ownerforma de recuperar los tokens en caso de que el beneficiario no pueda firmar una transacción cuando sea el momento de reclamar los tokens depositados en este contrato. Las validaciones de entrada podrían fortalecerse, pero quería que fuera lo más breve posible para mayor claridad.

Espero eso ayude.

Eso es muy, muy útil, gracias @rob. Entonces, la lógica del bloqueo de tiempo no tiene que vivir en el contrato inteligente de token, ¿verdad? En mi caso, el contrato inteligente de token ya está implementado, por lo que la lógica del contrato de adjudicación y bloqueo de tiempo debe vivir por sí misma.
Yo diría que la lógica del bloqueo no debería vivir en el token de la misma manera que la lógica de un dólar está separada de la lógica de una caja fuerte con bloqueo de tiempo. Habiendo dicho eso, estoy al tanto de las propuestas que mezclan las dos preocupaciones, particularmente en el ámbito de la emisión de tokens de seguridad. Podría mirar los tramos ERC1400, por ejemplo.
Eso es simplemente asombroso. Gracias 🙌. Una cosa que noté en la función de depósito: está llamando a transferir del beneficiario al contrato inteligente, lo que significa que el beneficiario ya debe tener los tokens para bloquearlos, ¿correcto?
¿Sabes que? Eso es un error. Olvidé que el emisor los tendría todos para empezar y la "ceremonia" de despliegue incluiría depositar los tokens adquiridos en cajas cerradas. Lo arreglaré para que sea una mejor referencia para alguien más que pase.
Seguro muchas gracias. Entonces, cambió a msg.sender, que podría ser la dirección del contrato inteligente del token que contiene todo el token, ¿verdad?
msg.senderdebe ser la dirección que implementó ambos contratos, pero no el contrato en sí. La dirección del contrato del token es importante, por lo que se pasa al constructor de la caja de seguridad en el momento de la implementación.