Triángulos Imposibles y Concesiones
Al embarcarnos en un viaje fascinante en el mundo DeFi, usualmente comienza con una inmersión profunda en el whitepaper Bitcoin. Allí es cuando encontré la intriga con el “triángulo imposible”, un concepto que elocuentemente ilustra el balance complejo entre la descentralización, seguridad y escalabilidad.
En esencia, la descentralización representa un principio fundamental del espacio de las cripto, permitiendo a los individuos la libertad para volverse validadores dentro de la red. Sin embargo, cuando consideramos los requisitos fundamentales en una blockchain pública, la seguridad surge como el eje. Es la fundación no negociable en la que todo lo demás descansa, convirtiéndolo en la piedra angular del triángulo imposible.
En contraste, la escalabilidad usualmente toma el asiento trasero en la ecuación, dando paso a los otros dos componentes críticos. Por eso es que te has dado cuenta que las tasas de la transacción en Bitcoin o las tasas de gas en Ethereum sobrepasan aquellos de los métodos tradicionales de pago, a pesar de la velocidad perceptible o la desventaja del ancho de banda.
Aún así, incluso con las restricciones de escalabilidad han surgido soluciones ingeniosas. Permiten transacciones complejas de los token con la mayor eficiencia, mientras mantienen diseños elegantes para los contratos inteligentes. Una creación particularmente cautivadora que emerge luego del Verano de fervor post DeFi, es la introducción en los tokens de reflejo: un acercamiento único y creativo para apoyar las tokenomics para asegurar el éxito continuo de las DeFi.
¿Qué son los tokens de reflejo?
Imagina que cada vez que un titular de un token hace una transferencia o un intercambio, un pequeño porcentaje de ese token es deducido desde su balance. Lo que pasa después es donde la magia sucede: una porción de este token regresa a la piscina de liquidez, mientras que el resto es distribuído junto a los demás titulares. El cálculo subyacente y la lógica del código puede que parezca sencillo en el mundo de las finanzas tradicionales. Sin embargo, en el reino de las criptomonedas, introducir una tarifa en cada transferencia, combinado con recalcular el balance con cada dirección envuelta puede resultar en grandes consumos de gas.
Aquí entra el concepto ingenioso de los tokens de reflejo: una innovación de código abierto, promovida por el renombrado proyecto SafeMoon. No sólo provee conocimientos valiosos sino también sirve como una fuente de inspiración para mejorar la eficiencia de gas y simplificar el proceso entero a la mayor simplicidad.
Explicación del Código
Variables de la Administración de Cuenta
En primer lugar, dos variables son las más importantes para, respectivamente, guardar el balance de la cuenta del token de reflejo y el saldo de la cuenta del token original. Bien sea que una cuenta o no pueda recibir las recompensas, también está destrozado por las variables entre ellos.
mapping(address => uint256) private _rOwned; // tokens reflejados poseídos
mapping(address => uint256) private _tOwned; // token poseído
mapping(address => mapping(address => uint256)) private _allowances;
mapping(address => bool) private _isExcludedFromFee; // Cuenta que paga o no paga la tasa de la transacción
mapping(address => bool) private _isExcluded; // Las cuentas que recibirán recompensas o no (si es verdadero: (la cuenta se excluye de recibir la recompensa), si es falsa: la cuenta no se excluye: por lo tanto, puede recibir recompensas)
address[] private _excluded; // Las cuentas que no reciben recompensas
Variables Aritméticas
La única cosa que vale mencionar para las variables de abajo es que la cantidad de los tokens de reflejo es exactamente ciertos tiempos de cantidad del token original.
uint256 private constant MAX = ~uint256(0); // 2^256 -1 = 1.15792089237316195423570985008687907853269984665640564039457584007913129639935×10⁷⁷
uint256 private _tTotal = 1000000000 * 10**6 * 10**9; // 10^9 * 10^6 * 10^9 = 10^24 = One Septillion
uint256 private _rTotal = (MAX - (MAX % _tTotal)); // 1.15792089237316195423570985008687907853269984665640564×10^77
/// @notice Todas las tarifas coleccionadas a través de las transferencias
uint256 private _tFeeTotal;
string private _name = "Reflecive Token";
string private _symbol = "RFT";
uint8 private _decimals = 9;
uint256 public _taxFee = 5;
uint256 private _previousTaxFee = _taxFee;
uint256 public _liquidityFee = 5;
uint256 private _previousLiquidityFee = _liquidityFee;
IUniswapV2Router02 public immutable uniswapV2Router;
address public immutable uniswapV2Pair;
bool inSwapAndLiquify;
bool public swapAndLiquifyEnabled = true;
uint256 public _maxTxAmount = 5000000 * 10**6 * 10**9; // 50^21
uint256 private numTokensSellToAddToLiquidity = 500000 * 10**6 * 10**9; // 50^20
Balance del Cálculo
Hay dos cálculos principales para el balance del cálculo. En el primero, usamos un valor de tasa para dividir la cantidad de los tokens de reflejo de una dirección para calcular el balance original de su token.
balanceOf(address) = rAmount / currentRate
El segundo es sobre cómo el valor es calculado. Hasta ahora, sabemos que el denominador de la fórmula es un número fijo el cual es igual a la cantidad total del token original (es decir, _tTotal
).
Ahora tienes un entendimiento superficial de cuando el suministro total de tokens reflejantes disminuye, la tasa también disminuye. Cuando esa situación ocurre durante el intercambio o las transferencias, la tasa disminuye. Combinando esto con la primera fórmula, la cantidad del token original en la cuenta del usuario se incrementará.
currentRate = rSupply / tSupply
function balanceOf(address account) public view override returns (uint256) {
if (_isExcluded[account]) return _tOwned[account];
return tokenFromReflection(_rOwned[account]);
}
/// @notice Esta función calcula cuántos tokens hay por reflejo
/// @dev En el reflejo inicial el valor debería ser mayor, o puede que tengas una idea
/// ejecutando {reflectionFromToken} para obtener el reflejo del token
function tokenFromReflection(uint256 rAmount) public view returns (uint256) {
require(rAmount <= _rTotal, "Amount must be less than total reflections");
uint256 currentRate = _getRate(); // 1.15792089237316195423570985008687907853269984665640564×10⁵³
return rAmount.div(currentRate); // (2 * 10^53) / (1.15792089237316195423570985008687907853269984665640564×10⁵³) = 1
}
/// @notice Calcula la tasa actual del token.
/// @return Tasa actual de la fórmula simple (el reflejo de la oferta restante / oferta restante total)
function _getRate() private view returns (uint256) {
(uint256 rSupply, uint256 tSupply) = _getCurrentSupply(); // (1.1579×10^53 , 10^24)
return rSupply.div(tSupply); // 1.15792089237316195423570985008687907853269984665640564×10⁵³
}
Token de Transferencia
Hay condiciones típicas de la transferencia del token, lo que quiere decir que ni el remitente ni el receptor no son excluídos desde la distribución de la recompensa, la implementación del código es una función _transferStandard
.
/// @notice Esta función obtiene el reflejo y el valor de la transferencia (incluyendo el reflejo y la atasa de la transferencia.
/// sustrae la cantidad del reflejo del remitente desde el balance de su reflejo
/// añade la cantidad de reflejo de transferencia al balance de la transferencia del receptor
/// contrato inteligente toma la liquidez y refleja ambas tasas
/// @param {sender} dirección del remitente
/// @param {recipient} dirección del receptor
/// @param {tAmount} cantidad de transferencia
function _transferStandard(
address sender,
address recipient,
uint256 tAmount
) private {
(
uint256 rAmount,
uint256 rTransferAmount,
uint256 rFee,
uint256 tTransferAmount,
uint256 tFee,
uint256 tLiquidity
) = _getValues(tAmount);
_rOwned[sender] = _rOwned[sender].sub(rAmount);
_rOwned[recipient] = _rOwned[recipient].add(rTransferAmount);
_takeLiquidity(tLiquidity);
_reflectFee(rFee, tFee);
emit Transfer(sender, recipient, tTransferAmount);
}
Antes de actualizar el balance de la cuenta, necesitas calcular la transferencia, la tasa del impuesto y los valores de la tasa de liquidez para ambos el token original y de reflejo. Los valores originales del token son calculados en primer lugar y luego los valores del token reflejo son computados a través de la multiplicación de tasas a ellos.
El balance del token reflejo del emisor y receptor es actualizado, sustrayendo o añadiendo valores a través de _getValues
.
/// @notice Calcula la Transferencia y los valores de Reflejo
/// @param {tAmount} Cantidad total de la transferencia
/// @return rAmount Cantidad reflejo
/// @return rTransferAmount Cantidad de la transferencia reflejo
/// @return rFee tasas de reflejo
/// @return tTransferAmount cantidad de transferencia
/// @return tFee tasas de transferencia
/// @return tLiquidity transferencia de liquidez
function _getValues(uint256 tAmount)
private
view
returns (
uint256,
uint256,
uint256,
uint256,
uint256,
uint256
)
{
// 100000000000 (tAmount)
(uint256 tTransferAmount, uint256 tFee, uint256 tLiquidity) = _getTValues(tAmount); // (90000000000 , 5000000000 , 5000000000 )
(uint256 rAmount, uint256 rTransferAmount, uint256 rFee) = _getRValues(
tAmount,
tFee,
tLiquidity,
_getRate()
);
//(9.26336713898529563388567880069503262826159877325124512×10⁶³ , 5.7896044618658097711785492504343953926634992332820282×10⁶² , 5.7896044618658097711785492504343953926634992332820282×10⁶²)
return (rAmount, rTransferAmount, rFee, tTransferAmount, tFee, tLiquidity);
}
La cantidad de la tasa de liquidez se graba en el balance del token reflejo del contrato del token. Si el contrato se excluye de recibir recompensas, entonces se requiere que el balance original del token sea refrescado. Y luego del estado de la exclusión se revierte a falso, el balance del token original será configurado a 0
/// @notice Esta función incrementará el reflejo y el balance de transferencia del contrato inteligente por rLiquidity y tLiquidity
/// @param {tLiquidity} Es calculado por la función calculateLiquidityFee()
function _takeLiquidity(uint256 tLiquidity) private {
uint256 currentRate = _getRate();
uint256 rLiquidity = tLiquidity.mul(currentRate);
_rOwned[address(this)] = _rOwned[address(this)].add(rLiquidity);
if (_isExcluded[address(this)]) _tOwned[address(this)] = _tOwned[address(this)].add(tLiquidity);
}
Con la tarifa del impuesto cortada desde la cantidad total del token reflejo, el valor del intercambio entre el token reflejo y el token original sube, lo que quiere decir que la misma cantidad del token reflejo puede convertirse en una mayor cantidad del token original.
/// @notice Tasas reflejo, sustrae rFee desde _rTotal y añade tFee en _tFeeTotal
/// @param {rFee} tasa reflejo
/// @param {tFee} tasa de transferencia
function _reflectFee(uint256 rFee, uint256 tFee) private {
_rTotal = _rTotal.sub(rFee);
_tFeeTotal = _tFeeTotal.add(tFee);
}
La lógica de la implementación del código bajo las diferentes condiciones de la transferencia del código es muy similar a la función _transferStandard
.
/// @notice Esta función realiza las revisiones de la tarifa y luego, de acuerdo al remitente y el receptor
/// excluido las marcas de transferencia dado la cantidad del receptor.
/// @param {sender} dirección del emisor
/// @param {recipient} dirección del receptor
/// @param {amount} cantidad de transferencia
/// @param {takeFee} marca el cargo de una tarifa o no
function _tokenTransfer(
address sender,
address recipient,
uint256 amount,
bool takeFee
) private {
// si tomar la tarifa es falso, removeAllFee() se llama para configurar las tarifas (taxFee and liquidityFee) a cero
if (!takeFee) removeAllFee();
if (_isExcluded[sender] && !_isExcluded[recipient]) {
_transferFromExcluded(sender, recipient, amount);
} else if (!_isExcluded[sender] && _isExcluded[recipient]) {
_transferToExcluded(sender, recipient, amount);
} else if (!_isExcluded[sender] && !_isExcluded[recipient]) {
// La función _transferStandard se llama si ambos el emisor y receptor no son excluidos desde las recompensas recibidas (ambos pueden recibir recompensas)
_transferStandard(sender, recipient, amount);
} else if (_isExcluded[sender] && _isExcluded[recipient]) {
_transferBothExcluded(sender, recipient, amount);
} else {
_transferStandard(sender, recipient, amount);
}
if (!takeFee) restoreAllFee();
}
Otros Elementos para la bomba de SafeMoon
Tiempo: Una apuesta bien colocada
Todo comenzó en Noviembre 2021 cuando profundicé el tiempo de verificación en el proxy del token del contrato inteligente. Antes, el mundo de los memes en cadena aún se mantenía, con la sombra de los retos subsecuentes como el escándalo de SBF y el espiral de muerte que aún se asoma de LUNA. Los inversores minoristas buscaban ansiosamente el siguiente Dogecoin o la siguiente sensación de paquete de meme como la locura de WallStreetBets. Con este contexto, Ethereum y Bitcoin estaban alcanzando su récord máximos, saturando el mercado con liquidez. Fue precisamente en esta coyuntura que SafeMoon hizo su debut, capitalizando en la tormenta perfecta.
Operaciones de Mercado: El Liderazgo Visionario
En la cabeza de SafeMoon estaba John Karony, un líder visionario adepto en la administración de programa y la escritura técnica. Dirigió el proyecto con una serie de estrategias de mercados bien creadas, creando un nuevo estándar en confiabilidad para los inversores minoristas. Mientras muchos proyectos, en ese entonces, expresaron su preocupación distribuyendo un intercambio significativo de tokens para empresas o miembros principales, SafeMoon tomó un camino distinto. No sólo quemaron todos los tokens del desarrollador en el lanzamiento pero también abrazaron mecanismos IEO e IDO, justos y transparentes. Los tokenomics y el esquema del reflejo innovador fueron ejecutados con precisión. Trillones de monedas fueron sistemáticamente removidas de la circulación para mantener un suministro escaso, creando una ola de entusiasmo en el mercado.
Espiral de Muerte
Fundamentales cero y uso
Entre la locura de la subida de precio realizada por el FOMO (Fear of Missing Out, miedo a perderse (algo)), el valor del mercado de SafeMoon una vez se elevó a más de mil millones de dólares. Sin embargo, desde entonces se ha desplomado por más de 90% en su valor de mercado y su bajo volumen de intercambio ahora da la apariencia de un proyecto inactivo. Los resultados indican una falta de utilidad o incentivos para las manos de diamantes si la tendencia de precios cambia de una tendencia en alta a una tendencia en baja.
Más aún, la inactividad del proyecto en ambos, el desarrollo y el mercado de intercambio, sugiere que el equipo no ha mostrado mucho compromiso por mantener o mejorar la utilidad del token.
¿Es un caso de mal tokenomics?
Se parece más a las ponzinomics más que a un pobre tokenomics. Estos dos conceptos comparten algunas similitudes. En un esquema Ponzi, ganas dividendos desde nuevos participantes uniéndose al esquema, mientras que en monedas terribles, ganas reflejos desde otros comprando.
Sin embargo, hay un inconveniente notable: los propietarios están obligados a pagar impuestos cuando se involucran en el trading. Esto quiere decir que el enfoque primario del proyecto es en inflar el precio, pero usualmente esa estrategia es de corto plazo.
Fuente
explicación del código en video
Este artículo es una traducción de 0xCryptoQuant, hecha por Héctor Botero. Puedes encontrar el artículo original aquí.
Sería genial escucharte en nuestro Discord, puedes contarnos tus ideas, comentarios, sugerencias y dejarnos saber lo que necesitas.
Si prefieres puedes escribirnos a @web3dev_es en Twitter.
Discussion (0)