El MEV (extracción máxima de valor para los mineros) es un problema que existe actualmente en PoW (prueba de trabajo) pero que se accentuará en PoS (prueba de staking). El MEV dá una ventaja on-chain a los mineros sobre los usuarios normales. No queremos esto. Por eso existen ya un par de ideas a corto o largo plazo para prevenir esto: soluciones como flashbots o a nivel de protocolo. A pesar de esto es un problema que persiste y qué mejor que atacarlo desde diferentes frentes. En este video mostramos cómo desde Solidity podemos suprimir uno de los ataques mas comunes, exploraremos como prevenir el ataque del sandwitch desde un token ERC20.
En eigenphi puedes encontrar ejemplos de ataques del sandwitch en mainnet.
Antes de comenzar
Para este tutorial ocuparás Metamask u otra wallet compatible con fondos en Goerli que puedes obetener desde un faucet.
Token ERC20 con mecanismo anti-sandwitch
Asegúrate de usar un router que exista en el blockchain que estás utilizando.
- Uniswap Router:
0x7a250d5630B4cF539739dF2C5dAcb4c659F2488D
- Quickswap Router:
0xa5E0829CaCEd8fFDD4De3c43696c57F7D7A678ff
- Pancakeswap Router:
0x10ED43C718714eb63d5aA57B78B54704E256024E
// SPDX-License-Identifier: MIT
pragma solidity 0.8.16;
import "@openzeppelin/contracts/token/ERC20/ERC20.sol";
interface IUniswapV2Factory {
function createPair(address tokenA, address tokenB) external returns (address pair);
}
interface IUniswapV2Router {
function factory() external pure returns (address);
function WETH() external pure returns (address);
}
contract MyToken is ERC20 {
mapping(address => uint256) public lastTxByAddress;
uint public blockCooldownAmount = 1;
address pair;
constructor() ERC20("My Token", "MTKN") {
_mint(msg.sender, 1_000_000 ether);
IUniswapV2Router uniswapRouter = IUniswapV2Router(0x7a250d5630B4cF539739dF2C5dAcb4c659F2488D);
pair = IUniswapV2Factory(uniswapRouter.factory()).createPair(address(this), uniswapRouter.WETH());
}
function _beforeTokenTransfer(
address from,
address to,
uint256 amount
) internal override {
amount;
if(from == pair)
{
ensureMaxTxFrequency(to);
lastTxByAddress[to] = block.number;
} else if(to == pair)
{
ensureMaxTxFrequency(from);
lastTxByAddress[from] = block.number;
}else
{
ensureMaxTxFrequency(from);
lastTxByAddress[from] = block.number;
ensureMaxTxFrequency(to);
lastTxByAddress[to] = block.number;
}
}
function ensureMaxTxFrequency(address addr) internal virtual {
bool isAllowed = lastTxByAddress[addr] == 0 ||
((lastTxByAddress[addr] + blockCooldownAmount) < (block.number + 1));
require(isAllowed, "Max tx frequency exceeded!");
}
}
Gracias por ver este video!
Sígannos en dev.to y en Youtube para todo lo relacionado al desarrollo en Blockchain en Español.