Cómo crear direcciones de contribución únicas para un sistema de referencia por contrato inteligente

Tuve algunos problemas con mi contrato inteligente. Quiero poder asignar tokens de referencia a cada persona que participó en el programa de referencia de ICO. Para hacer esto, el contrato inteligente debe ser capaz de distinguir las contribuciones realizadas y vincularlas a un determinado participante. Estoy buscando una forma de permitir que el contrato inteligente cree direcciones de contribución únicas para cada participante que se registre en la ICO. Estas direcciones recibirán las contribuciones y las transferirán inmediatamente a la dirección de contrato "principal", conociendo de esta manera cada contribución realizada por cada contribuyente por separado, incluso si contribuye desde múltiples billeteras. ¿Cómo puedo hacer esto?

No lo entiendo, ¿solo quiere saber CUÁNDO contribuyó un colaborador?
No, quiero saber QUIÉN es el contribuyente, incluso si contribuye desde 3/4 direcciones diferentes. Quiero una forma de crear una dirección única para cada participante de ICO, para saber quién envía qué.
No puede asignar una dirección desde el contrato inteligente, pero puede asignarles una identificación.
¿Y cómo funciona eso exactamente?
Entonces, para que quede claro: una persona que quiere contribuir se registra en un sitio web y obtiene su tablero. En este tablero, obtendrá un enlace de referencia y podrá ver la cantidad de personas que se registraron a través de ese enlace, y luego verá el monto total de todas las contribuciones realizadas por esas personas. Necesito saber cómo puedo distinguir a estos contribuyentes, dándoles a cada uno de ellos una dirección de contribución de la cual el contrato inteligente sabrá quién es. De lo contrario, no hay forma de saber quién aportó qué.

Respuestas (2)

Según los comentarios en el OP:

No puede asignar una nueva dirección a un remitente mientras está en un contrato inteligente. Además, dentro del contrato, hay una nueva forma de saber qué dirección te pertenece. Además, este es solo mi punto de vista, el usuario envía ether desde donde quiere, generalmente desde una sola cuenta. Es su responsabilidad enviar desde donde quieran, no la nuestra.

Pero, incluso si logra identificar a los usuarios, crearía un mapeo con un uint como clave y un mapeo como valor. Esta otra asignación sería la lista de direcciones desde las que el usuario envió ether. De esta manera, puede identificar las direcciones.

¿Y si hago contratos de receptor para cada participante y un contrato de acumulación separado que acumula todos los montos de los contratos de receptor? ¿Cómo activaría este contrato de receptor para enviar automáticamente cada contribución al contrato de acumulación?
Contratos para manejar contratos para... ? ¿Tiene alguna idea de cuánto le costará esto a usted (o al remitente)? Mucho dinero. Con solidez, haz las cosas simples, no complicadas, o perderás mucho dinero.
¿Cómo me sugieres que lo haga entonces?

Tienes que tener dos contratos: Principal y Receptor. Contrato principal que tendrá una función para crear una instancia de un contrato de Receptor y registrar esta instancia en el mapeo para asegurarnos de que vamos a recibir pagos solo de Receptores válidos.

El contrato del receptor implementará la función de reserva pagadera por defecto que transfiere cualquier valor al contrato principal. Solo hay una pequeña cantidad de gas que se puede usar mediante la función de pago predeterminada cuando se envía ETH, por lo que puede solicitar a sus usuarios que llamen a la función especial para realizar sus pagos. Lo llamé PayTransfer. El código de trabajo, probado en Remix está a continuación. Para probarlo tienes que:

  1. Crear contrato principal
  2. Llame a la función AddReceiver en el contrato principal.
  3. La nueva dirección del receptor se mostrará en el evento NewReceiver y también en la variable pública lastReceiver.
  4. Entonces tienes que hacer un pago al contrato del receptor. En remix, puede adjuntar el contrato de PaymentReceiver a la dirección que obtuvo en el paso anterior. Use el botón En la dirección.

  5. Una vez que se realiza el pago, puede verificar el saldo de su contrato principal, el saldo del receptor y el valor de la contribución del receptor al contrato principal utilizando las siguientes funciones:

    • Mi balance
    • ReceptorBalance
    • Contribución del receptor

En caso de que la función de respaldo pagable predeterminada no funcione (funciona en Remix), puede pedir a sus clientes que llamen a la función PayTransfer para realizar sus pagos o modificar la función de respaldo para no transferir msg.value al contrato principal y usar la función RetrievePayment para transferir ETH a su contrato principal (tendrá que pagar el gas en este caso).

Espero que esto ayude.

pragma solidity ^0.4.24;


contract PaymentReceiver {

    Main public main;

    function () payable {
        main.ReceivePayment.value(msg.value)();
    }

    function PayTransfer() public payable {
    main.ReceivePayment.value(msg.value)();
    }

    function RetreivePayment() public {
        main.ReceivePayment.value(address(this).balance)();
    }
    constructor() public {
        main = Main( msg.sender);
    }
}


contract Main {

    event NewReceiver(address receiver);
    event ReceivedPayment(address receiver, uint256 value);
    mapping(address => uint256) contributions;
    mapping (address=>bool) validReceiver;
    address public lastReceiver;

    function ReceivePayment() public payable {
        require (validReceiver[msg.sender]);
        contributions[msg.sender] = contributions[msg.sender] + msg.value;
        emit ReceivedPayment(msg.sender,msg.value);

    }

    function AddReceiver() public {
        PaymentReceiver receiver = new PaymentReceiver();
        validReceiver[address(receiver)] = true;
        lastReceiver = address(receiver);
        emit NewReceiver(receiver);
    }

    function MyBalance() public view  returns (uint) {

    return address(this).balance;

    }

    function ReceiverBalance(address receiver) public view returns (uint256) {
        require(validReceiver[receiver]);
        return address(receiver).balance;
    }

    function ReceiverContribution(address receiver) public view returns (uint256) {
        return contributions[address(receiver)];
    }


}