Los contratos bulker en Compound V3 son contratos similares a un multicall para agrupar varias transacciones en lotes.
Por ejemplo, si quisiéramos suministrar Ether, LINK y wBTC como garantía y pedir prestado USDC contra ellos en una sola transacción, podemos hacerlo.
También podemos reducir las tenencias de garantía y retirar un préstamo en una sola transacción, como lo demuestra la captura de pantalla a continuación. Por supuesto, esto supone que nos mantenemos dentro de los límites del factor de garantía.

invoke()
El bulker no se comporta como un multicall tradicional donde acepta una lista de calldata arbitraria. En su lugar, toma dos argumentos: una lista de acciones (de las cuales hay 6 opciones) y los argumentos para suministrarles. La función se muestra a continuación. Específicamente, podemos
- suministrar un ERC-20 (
ACTION_SUPPLY_ASSET) - suministrar ETH (
ACTION_SUPPLY_NATIVE_TOKEN) - transferir un activo (
ACTION_TRANSFER_ASSET), consulte nuestro artículo sobre cómo Compound V3 se comporta como un token ERC-20 de rebase para ver cómo funciona esto - retirar un ERC-20 (
ACTION_WITHDRAW_ASSET) - retirar ETH (
ACTION_WITHDRAW_NATIVE_TOKEN) - reclamar las recompensas de COMP acumuladas. La función subyacente claimReward interactuará con el contrato de recompensas en lugar de con el contrato de préstamos principal (Comet.sol).

Invoke iterará a través de las acciones y llamará a Comet (o al contrato de recompensas) con los argumentos suministrados.
Aunque podría haber sido más eficiente en cuanto a gas colocar este código en el contrato principal, usar msg.value en un bucle, especialmente al invocar delegatecall, no es seguro. Vea el problema de práctica al final de este artículo.
Compound tiene cuidado de asegurarse de que msg.value se deduzca en lugar de reutilizarse, lo que podría conducir a un doble gasto — vea los recuadros amarillos.
Se podría argumentar que esto podría haber sido optimizado en cuanto a gas decidiendo las acciones con un indicador de 1 byte en lugar de un indicador de cadena ASCII de 32 bytes.
Los bulkers son sin custodia
El bulker nunca retiene los tokens del usuario. En su lugar, el usuario otorga aprobación al bulker y el bulker suministra los activos a Compound en nombre del usuario. Compound no asume que msg.sender es el depositante; hacerlo generalmente no es un buen patrón de diseño porque rompe la componibilidad — impide que otros contratos actúen en nombre del usuario.
Rescate de tokens
En el caso de que los usuarios transfieran tokens accidentalmente al bulker, un administrador puede retirar los tokens. Tenga en cuenta que tenemos funciones separadas para retirar el ETH atascado y los tokens ERC-20 atascados.

Manejo de tokens ERC-20 no estándar
Una de las desviaciones más comunes de la especificación del token ERC-20 es no devolver un valor booleano. Varios tokens ERC-20 no devuelven un booleano, sino que revierten en caso de fallo.
Para manejar ambas situaciones al tratar con activos ERC-20, Compound implementa el siguiente código:

No hay valor de retorno de IERC20NonStandard — revertirá si se trata de un token ERC-20 no estándar. Para manejar la posibilidad de que en realidad sea un token ERC-20 estándar, el caso donde el tamaño de los datos de retorno es de 32 bytes significará que el token sí devolvió un valor. Si el valor devuelto es 1, tuvo éxito, y de lo contrario falló. Los diferentes escenarios se capturan en la matriz a continuación.

Esencialmente, tenemos éxito en los casos en que el (token no revierte Y no devuelve nada) O (token no revierte Y devuelve verdadero). Fallamos en los casos en que (token revierte) O (token no revierte Y devuelve falso).
La interfaz IERC20Nonstandard simplemente define un token ERC20 que no devuelve ningún booleano.

Problemas de práctica
Pueden suceder cosas malas al usar msg.value dentro de un bucle. Vea estos dos problemas de práctica:
Aprenda más con RareSkills
Por favor, consulte nuestro bootcamp de web3 para obtener más información.
Publicado originalmente el 9 de enero de 2024