¿Cómo restringir una función en un contrato para que solo pueda ser llamada por un contrato designado?

Primero, conozco una pregunta similar , pero esa respuesta no es suficiente.

Digamos que implementé un contrato A, luego implementé otro contrato B algún tiempo después. Quiero asegurarme de que una función A.f1()en A solo se pueda llamar desde el contrato B. Para hacerlo, implemento una función register(address trusted_contract)para registrar B en A, que básicamente almacena la dirección de B en una matriz en A. Como soy dueño de A, Soy el único que puede llamarlo para registrar una dirección.

Ahora, si B llama A.f1(), dentro f1()de , compruebo si msg.senderestá en la matriz y decido si atiendo la llamada.

¿Esta es la manera correcta de hacerlo?

Si es así, todavía tengo una pregunta. ¿Qué impide que otro contrato C envíe un msj y diga que es B? Tengo entendido que, a diferencia de una cuenta externa, un contrato no tiene una clave privada y, por lo tanto, no puede firmar un mensaje. Si es así, ¿cómo verifica el receptor A que la persona que llama es el contrato B y no un mal actor C?

Respuestas (2)

¿Esta es la manera correcta de hacerlo?

Sí, excepto que en lugar de una matriz, debe usar un mapa para una búsqueda eficiente.

Si es así, ¿cómo verifica el receptor A que la persona que llama es el contrato B y no un mal actor C?

Hay 2 formas en que un "atacante" puede actuar:

  1. Envía una transacción directamente a tu contrato A.
  2. Envíe una transacción a algún contrato X (diferente del contrato B), luego dentro del contrato X se realizará una llamada de mensaje a su contacto A.

Dentro del contrato A estarán disponibles dos propiedades:

  • tx.origin- la dirección de la cuenta externa.
  • msg.sender- la dirección de la cuenta externa para el caso 1; dirección del contrato X para el caso 2.

msg.senderes lo que estarás comprobando para comprobar que la llamada se hace desde el contrato B.

En ambos casos, el "atacante" no puede fingir ser el contrato B:

  • para el 1er caso necesitaría firmar la transacción con la clave privada del contrato B que no existe;
  • para el segundo caso , no tiene control msg.senderporque lo maneja el EVM : cuando se realiza una llamada de mensaje desde el contrato X, el EVM debe configurar msg.senderpara que sea la dirección del contrato X.

Entonces, a menos que el "atacante" envíe la transacción al contrato B, no habrá forma de que finja ser el contrato B.

¡Gracias! Lo que en mi mente era el ataque 2, y lo que dijiste me aclaró las dudas. "¡Él no tiene control sobre msg.sender porque lo maneja el EVM"!

Si, eso es correcto. Lo que impide que una cuenta envíe una transacción como contrato B es que la cuenta necesitaría el par de claves pública/privada para firmar la transacción bajo la identidad del contrato.