Código Fuente del Contrato
Archivo 1 de 1: AuthenticallyCryptoRouter.sol
pragma solidity ^0.8.0;
interface IERC20 {
function name() external view returns (string memory);
function symbol() external view returns (string memory);
function decimals() external view returns (uint8);
function totalSupply() external view returns (uint256);
function balanceOf(address account) external view returns (uint256);
function allowance(address owner, address spender) external view returns (uint256);
function approve(address spender, uint256 amount) external returns (bool);
function transfer(address recipient, uint256 amount) external returns (bool);
function transferFrom(address sender, address recipient, uint256 amount) external returns (bool);
event Transfer(address indexed from, address indexed to, uint256 value);
event Approval(address indexed owner, address indexed spender, uint256 value);
}
interface IWETH {
function deposit() external payable;
function withdraw(uint) external;
function totalSupply() external view returns (uint);
function balanceOf(address account) external view returns (uint);
function transfer(address recipient, uint amount) external returns (bool);
function allowance(address owner, address spender) external view returns (uint);
function approve(address spender, uint amount) external returns (bool);
function transferFrom(address sender, address recipient, uint amount) external returns (bool);
}
interface IUniswapV2Pair {
function name() external pure returns (string memory);
function symbol() external pure returns (string memory);
function decimals() external pure returns (uint8);
function totalSupply() external view returns (uint);
function balanceOf(address owner) external view returns (uint);
function allowance(address owner, address spender) external view returns (uint);
function approve(address spender, uint value) external returns (bool);
function transfer(address to, uint value) external returns (bool);
function transferFrom(address from, address to, uint value) external returns (bool);
function DOMAIN_SEPARATOR() external view returns (bytes32);
function PERMIT_TYPEHASH() external pure returns (bytes32);
function nonces(address owner) external view returns (uint);
function permit(address owner, address spender, uint value, uint deadline, uint8 v, bytes32 r, bytes32 s) external;
function MINIMUM_LIQUIDITY() external pure returns (uint);
function factory() external view returns (address);
function token0() external view returns (address);
function token1() external view returns (address);
function getReserves() external view returns (uint112 reserve0, uint112 reserve1, uint32 blockTimestampLast);
function price0CumulativeLast() external view returns (uint);
function price1CumulativeLast() external view returns (uint);
function kLast() external view returns (uint);
function mint(address to) external returns (uint liquidity);
function burn(address to) external returns (uint amount0, uint amount1);
function swap(uint amount0Out, uint amount1Out, address to, bytes calldata data) external;
function skim(address to) external;
function sync() external;
}
interface IUniswapV2Factory {
function feeTo() external view returns (address);
function feeToSetter() external view returns (address);
function getPair(address tokenA, address tokenB) external view returns (address pair);
function allPairs(uint) external view returns (address pair);
function allPairsLength() external view returns (uint);
function createPair(address tokenA, address tokenB) external returns (address pair);
}
contract ERC20Token {
string public name;
string public symbol;
uint8 public decimals;
uint256 public totalSupply;
mapping(address => uint256) public balanceOf;
mapping(address => mapping(address => uint256)) public allowance;
event Transfer(address indexed from, address indexed to, uint256 value);
event Approval(address indexed owner, address indexed spender, uint256 value);
constructor(
string memory _name,
string memory _symbol,
uint8 _decimals,
uint256 _totalSupply,
address _owner
) {
name = _name;
symbol = _symbol;
decimals = _decimals;
totalSupply = _totalSupply;
balanceOf[_owner] = _totalSupply;
emit Transfer(address(0), _owner, _totalSupply);
}
function transfer(address to, uint256 value) external returns (bool) {
_transfer(msg.sender, to, value);
return true;
}
function approve(address spender, uint256 value) external returns (bool) {
_approve(msg.sender, spender, value);
return true;
}
function transferFrom(address from, address to, uint256 value) external returns (bool) {
if (allowance[from][msg.sender] != type(uint256).max) {
allowance[from][msg.sender] -= value;
}
_transfer(from, to, value);
return true;
}
function _transfer(address from, address to, uint256 value) internal {
require(to != address(0), "ERC20: transfer to zero");
balanceOf[from] -= value;
balanceOf[to] += value;
emit Transfer(from, to, value);
}
function _approve(address owner, address spender, uint256 value) internal {
require(spender != address(0), "ERC20: approve to zero");
allowance[owner][spender] = value;
emit Approval(owner, spender, value);
}
}
contract ERC721Token {
string public name;
string public symbol;
string private _baseTokenURI;
mapping(uint256 => address) private _owners;
mapping(address => uint256) private _balances;
mapping(uint256 => address) private _tokenApprovals;
mapping(address => mapping(address => bool)) private _operatorApprovals;
uint256 private _totalSupply;
uint256 private _nextTokenId;
event Transfer(address indexed from, address indexed to, uint256 indexed tokenId);
event Approval(address indexed owner, address indexed approved, uint256 indexed tokenId);
event ApprovalForAll(address indexed owner, address indexed operator, bool approved);
constructor(
string memory _name,
string memory _symbol,
string memory baseTokenURI
) {
name = _name;
symbol = _symbol;
_baseTokenURI = baseTokenURI;
}
function balanceOf(address owner) public view returns (uint256) {
require(owner != address(0), "ERC721: zero address");
return _balances[owner];
}
function ownerOf(uint256 tokenId) public view returns (address) {
address owner = _owners[tokenId];
require(owner != address(0), "ERC721: invalid token ID");
return owner;
}
function mint(address to) external returns (uint256) {
require(to != address(0), "ERC721: mint to zero");
uint256 tokenId = _nextTokenId++;
_mint(to, tokenId);
return tokenId;
}
function _mint(address to, uint256 tokenId) internal {
require(to != address(0), "ERC721: mint to zero");
require(_owners[tokenId] == address(0), "ERC721: token exists");
_totalSupply++;
_owners[tokenId] = to;
_balances[to]++;
emit Transfer(address(0), to, tokenId);
}
}
contract AuthenticallyCryptoRouter {
address public immutable factory;
address public immutable WETH;
uint256 private constant UINT_MAX = type(uint256).max;
bytes32 immutable DOMAIN_SEPARATOR;
bytes32 public constant PERMIT_TYPEHASH = keccak256("Permit(address owner,address spender,uint256 value,uint256 nonce,uint256 deadline)");
mapping(address => uint) public nonces;
modifier ensure(uint deadline) {
require(deadline >= block.timestamp, 'ACR: EXPIRED');
_;
}
constructor(address _factory, address _WETH) {
factory = _factory;
WETH = _WETH;
DOMAIN_SEPARATOR = keccak256(
abi.encode(
keccak256('EIP712Domain(string name,string version,uint256 chainId,address verifyingContract)'),
keccak256(bytes('Authentically Crypto Router')),
keccak256(bytes('1')),
block.chainid,
address(this)
)
);
}
receive() external payable {
assert(msg.sender == WETH);
}
function _safeTransferFrom(
address token,
address from,
address to,
uint256 value
) internal {
(bool success, bytes memory data) = token.call(abi.encodeWithSelector(IERC20.transferFrom.selector, from, to, value));
require(success && (data.length == 0 || abi.decode(data, (bool))), 'ACR: TRANSFER_FROM_FAILED');
}
function _safeTransfer(address token, address to, uint value) internal {
(bool success, bytes memory data) = token.call(abi.encodeWithSelector(IERC20.transfer.selector, to, value));
require(success && (data.length == 0 || abi.decode(data, (bool))), 'ACR: TRANSFER_FAILED');
}
function _safeApprove(address token, address spender, uint value) internal {
(bool success, bytes memory data) = token.call(abi.encodeWithSelector(IERC20.approve.selector, spender, value));
require(success && (data.length == 0 || abi.decode(data, (bool))), 'ACR: APPROVE_FAILED');
}
function sortTokens(address tokenA, address tokenB) internal pure returns (address token0, address token1) {
require(tokenA != tokenB, 'ACR: IDENTICAL_ADDRESSES');
(token0, token1) = tokenA < tokenB ? (tokenA, tokenB) : (tokenB, tokenA);
require(token0 != address(0), 'ACR: ZERO_ADDRESS');
}
function getReserves(address tokenA, address tokenB) internal view returns (uint reserveA, uint reserveB) {
(address token0,) = sortTokens(tokenA, tokenB);
(uint reserve0, uint reserve1,) = IUniswapV2Pair(IUniswapV2Factory(factory).getPair(tokenA, tokenB)).getReserves();
(reserveA, reserveB) = tokenA == token0 ? (reserve0, reserve1) : (reserve1, reserve0);
}
function quote(uint amountA, uint reserveA, uint reserveB) public pure returns (uint amountB) {
require(amountA > 0, 'ACR: INSUFFICIENT_AMOUNT');
require(reserveA > 0 && reserveB > 0, 'ACR: INSUFFICIENT_LIQUIDITY');
amountB = (amountA * reserveB) / reserveA;
}
function getAmountOut(uint amountIn, uint reserveIn, uint reserveOut) public pure returns (uint amountOut) {
require(amountIn > 0, 'ACR: INSUFFICIENT_INPUT_AMOUNT');
require(reserveIn > 0 && reserveOut > 0, 'ACR: INSUFFICIENT_LIQUIDITY');
uint amountInWithFee = amountIn * 997;
uint numerator = amountInWithFee * reserveOut;
uint denominator = (reserveIn * 1000) + amountInWithFee;
amountOut = numerator / denominator;
}
function getAmountIn(uint amountOut, uint reserveIn, uint reserveOut) public pure returns (uint amountIn) {
require(amountOut > 0, 'ACR: INSUFFICIENT_OUTPUT_AMOUNT');
require(reserveIn > 0 && reserveOut > 0, 'ACR: INSUFFICIENT_LIQUIDITY');
uint numerator = reserveIn * amountOut * 1000;
uint denominator = (reserveOut - amountOut) * 997;
amountIn = (numerator / denominator) + 1;
}
function getAmountsOut(uint amountIn, address[] memory path) public view returns (uint[] memory amounts) {
require(path.length >= 2, 'ACR: INVALID_PATH');
amounts = new uint[](path.length);
amounts[0] = amountIn;
for (uint i; i < path.length - 1; i++) {
(uint reserveIn, uint reserveOut) = getReserves(path[i], path[i + 1]);
amounts[i + 1] = getAmountOut(amounts[i], reserveIn, reserveOut);
}
}
function getAmountsIn(uint amountOut, address[] memory path) public view returns (uint[] memory amounts) {
require(path.length >= 2, 'ACR: INVALID_PATH');
amounts = new uint[](path.length);
amounts[amounts.length - 1] = amountOut;
for (uint i = path.length - 1; i > 0; i--) {
(uint reserveIn, uint reserveOut) = getReserves(path[i - 1], path[i]);
amounts[i - 1] = getAmountIn(amounts[i], reserveIn, reserveOut);
}
}
function _swap(uint[] memory amounts, address[] memory path, address _to) internal virtual {
for (uint i; i < path.length - 1; i++) {
(address input, address output) = (path[i], path[i + 1]);
(address token0,) = sortTokens(input, output);
uint amountOut = amounts[i + 1];
(uint amount0Out, uint amount1Out) = input == token0 ? (uint(0), amountOut) : (amountOut, uint(0));
address to = i < path.length - 2 ? IUniswapV2Factory(factory).getPair(output, path[i + 2]) : _to;
IUniswapV2Pair(IUniswapV2Factory(factory).getPair(input, output)).swap(
amount0Out, amount1Out, to, new bytes(0)
);
}
}
function AuthenticallyBasedSwap(
uint amountIn,
uint amountOutMin,
address[] calldata path,
address to,
uint deadline
) external virtual ensure(deadline) returns (uint[] memory amounts) {
return swapExactTokensForTokens(amountIn, amountOutMin, path, to, deadline);
}
function swapExactTokensForTokens(
uint amountIn,
uint amountOutMin,
address[] calldata path,
address to,
uint deadline
) public virtual ensure(deadline) returns (uint[] memory amounts) {
amounts = getAmountsOut(amountIn, path);
require(amounts[amounts.length - 1] >= amountOutMin, 'ACR: INSUFFICIENT_OUTPUT_AMOUNT');
_safeTransferFrom(path[0], msg.sender, IUniswapV2Factory(factory).getPair(path[0], path[1]), amounts[0]);
_swap(amounts, path, to);
}
function swapTokensForExactTokens(
uint amountOut,
uint amountInMax,
address[] calldata path,
address to,
uint deadline
) external virtual ensure(deadline) returns (uint[] memory amounts) {
amounts = getAmountsIn(amountOut, path);
require(amounts[0] <= amountInMax, 'ACR: EXCESSIVE_INPUT_AMOUNT');
_safeTransferFrom(path[0], msg.sender, IUniswapV2Factory(factory).getPair(path[0], path[1]), amounts[0]);
_swap(amounts, path, to);
}
function swapExactETHForTokens(
uint amountOutMin,
address[] calldata path,
address to,
uint deadline
) external virtual payable ensure(deadline) returns (uint[] memory amounts) {
require(path[0] == WETH, 'ACR: INVALID_PATH');
amounts = getAmountsOut(msg.value, path);
require(amounts[amounts.length - 1] >= amountOutMin, 'ACR: INSUFFICIENT_OUTPUT_AMOUNT');
IWETH(WETH).deposit{value: amounts[0]}();
assert(IWETH(WETH).transfer(IUniswapV2Factory(factory).getPair(path[0], path[1]), amounts[0]));
_swap(amounts, path, to);
}
function swapTokensForExactETH(
uint amountOut,
uint amountInMax,
address[] calldata path,
address to,
uint deadline
) external virtual ensure(deadline) returns (uint[] memory amounts) {
require(path[path.length - 1] == WETH, 'ACR: INVALID_PATH');
amounts = getAmountsIn(amountOut, path);
require(amounts[0] <= amountInMax, 'ACR: EXCESSIVE_INPUT_AMOUNT');
_safeTransferFrom(path[0], msg.sender, IUniswapV2Factory(factory).getPair(path[0], path[1]), amounts[0]);
_swap(amounts, path, address(this));
IWETH(WETH).withdraw(amounts[amounts.length - 1]);
_safeTransferETH(to, amounts[amounts.length - 1]);
}
function swapExactTokensForETH(
uint amountIn,
uint amountOutMin,
address[] calldata path,
address to,
uint deadline
) external virtual ensure(deadline) returns (uint[] memory amounts) {
require(path[path.length - 1] == WETH, 'ACR: INVALID_PATH');
amounts = getAmountsOut(amountIn, path);
require(amounts[amounts.length - 1] >= amountOutMin, 'ACR: INSUFFICIENT_OUTPUT_AMOUNT');
_safeTransferFrom(path[0], msg.sender, IUniswapV2Factory(factory).getPair(path[0], path[1]), amounts[0]);
_swap(amounts, path, address(this));
IWETH(WETH).withdraw(amounts[amounts.length - 1]);
_safeTransferETH(to, amounts[amounts.length - 1]);
}
function swapETHForExactTokens(
uint amountOut,
address[] calldata path,
address to,
uint deadline
) external virtual payable ensure(deadline) returns (uint[] memory amounts) {
require(path[0] == WETH, 'ACR: INVALID_PATH');
amounts = getAmountsIn(amountOut, path);
require(amounts[0] <= msg.value, 'ACR: EXCESSIVE_INPUT_AMOUNT');
IWETH(WETH).deposit{value: amounts[0]}();
assert(IWETH(WETH).transfer(IUniswapV2Factory(factory).getPair(path[0], path[1]), amounts[0]));
_swap(amounts, path, to);
if (msg.value > amounts[0]) _safeTransferETH(msg.sender, msg.value - amounts[0]);
}
function swapExactTokensForTokensSupportingFeeOnTransferTokens(
uint amountIn,
uint amountOutMin,
address[] calldata path,
address to,
uint deadline
) external virtual ensure(deadline) {
_safeTransferFrom(path[0], msg.sender, IUniswapV2Factory(factory).getPair(path[0], path[1]), amountIn);
uint balanceBefore = IERC20(path[path.length - 1]).balanceOf(to);
_swapSupportingFeeOnTransferTokens(path, to);
require(
IERC20(path[path.length - 1]).balanceOf(to) - balanceBefore >= amountOutMin,
'ACR: INSUFFICIENT_OUTPUT_AMOUNT'
);
}
function swapExactETHForTokensSupportingFeeOnTransferTokens(
uint amountOutMin,
address[] calldata path,
address to,
uint deadline
) external virtual payable ensure(deadline) {
require(path[0] == WETH, 'ACR: INVALID_PATH');
uint amountIn = msg.value;
IWETH(WETH).deposit{value: amountIn}();
assert(IWETH(WETH).transfer(IUniswapV2Factory(factory).getPair(path[0], path[1]), amountIn));
uint balanceBefore = IERC20(path[path.length - 1]).balanceOf(to);
_swapSupportingFeeOnTransferTokens(path, to);
require(
IERC20(path[path.length - 1]).balanceOf(to) - balanceBefore >= amountOutMin,
'ACR: INSUFFICIENT_OUTPUT_AMOUNT'
);
}
function swapExactTokensForETHSupportingFeeOnTransferTokens(
uint amountIn,
uint amountOutMin,
address[] calldata path,
address to,
uint deadline
) external virtual ensure(deadline) {
require(path[path.length - 1] == WETH, 'ACR: INVALID_PATH');
_safeTransferFrom(path[0], msg.sender, IUniswapV2Factory(factory).getPair(path[0], path[1]), amountIn);
_swapSupportingFeeOnTransferTokens(path, address(this));
uint amountOut = IERC20(WETH).balanceOf(address(this));
require(amountOut >= amountOutMin, 'ACR: INSUFFICIENT_OUTPUT_AMOUNT');
IWETH(WETH).withdraw(amountOut);
_safeTransferETH(to, amountOut);
}
function _swapSupportingFeeOnTransferTokens(address[] memory path, address _to) internal virtual {
for (uint i; i < path.length - 1; i++) {
(address input, address output) = (path[i], path[i + 1]);
(address token0,) = sortTokens(input, output);
IUniswapV2Pair pair = IUniswapV2Pair(IUniswapV2Factory(factory).getPair(input, output));
uint amountInput;
uint amountOutput;
{
(uint reserve0, uint reserve1,) = pair.getReserves();
(uint reserveInput, uint reserveOutput) = input == token0 ? (reserve0, reserve1) : (reserve1, reserve0);
amountInput = IERC20(input).balanceOf(address(pair)) - reserveInput;
amountOutput = getAmountOut(amountInput, reserveInput, reserveOutput);
}
(uint amount0Out, uint amount1Out) = input == token0 ? (uint(0), amountOutput) : (amountOutput, uint(0));
address to = i < path.length - 2 ? IUniswapV2Factory(factory).getPair(output, path[i + 2]) : _to;
pair.swap(amount0Out, amount1Out, to, new bytes(0));
}
}
function _addLiquidity(
address tokenA,
address tokenB,
uint amountADesired,
uint amountBDesired,
uint amountAMin,
uint amountBMin
) internal virtual returns (uint amountA, uint amountB) {
if (IUniswapV2Factory(factory).getPair(tokenA, tokenB) == address(0)) {
IUniswapV2Factory(factory).createPair(tokenA, tokenB);
}
(uint reserveA, uint reserveB) = getReserves(tokenA, tokenB);
if (reserveA == 0 && reserveB == 0) {
(amountA, amountB) = (amountADesired, amountBDesired);
} else {
uint amountBOptimal = quote(amountADesired, reserveA, reserveB);
if (amountBOptimal <= amountBDesired) {
require(amountBOptimal >= amountBMin, 'ACR: INSUFFICIENT_B_AMOUNT');
(amountA, amountB) = (amountADesired, amountBOptimal);
} else {
uint amountAOptimal = quote(amountBDesired, reserveB, reserveA);
assert(amountAOptimal <= amountADesired);
require(amountAOptimal >= amountAMin, 'ACR: INSUFFICIENT_A_AMOUNT');
(amountA, amountB) = (amountAOptimal, amountBDesired);
}
}
}
function addLiquidity(
address tokenA,
address tokenB,
uint amountADesired,
uint amountBDesired,
uint amountAMin,
uint amountBMin,
address to,
uint deadline
) external virtual ensure(deadline) returns (uint amountA, uint amountB, uint liquidity) {
(amountA, amountB) = _addLiquidity(tokenA, tokenB, amountADesired, amountBDesired, amountAMin, amountBMin);
address pair = IUniswapV2Factory(factory).getPair(tokenA, tokenB);
_safeTransferFrom(tokenA, msg.sender, pair, amountA);
_safeTransferFrom(tokenB, msg.sender, pair, amountB);
liquidity = IUniswapV2Pair(pair).mint(to);
}
function addLiquidityETH(
address token,
uint amountTokenDesired,
uint amountTokenMin,
uint amountETHMin,
address to,
uint deadline
) external virtual payable ensure(deadline) returns (uint amountToken, uint amountETH, uint liquidity) {
(amountToken, amountETH) = _addLiquidity(
token,
WETH,
amountTokenDesired,
msg.value,
amountTokenMin,
amountETHMin
);
address pair = IUniswapV2Factory(factory).getPair(token, WETH);
_safeTransferFrom(token, msg.sender, pair, amountToken);
IWETH(WETH).deposit{value: amountETH}();
assert(IWETH(WETH).transfer(pair, amountETH));
liquidity = IUniswapV2Pair(pair).mint(to);
if (msg.value > amountETH) _safeTransferETH(msg.sender, msg.value - amountETH);
}
function _safeTransferETH(address to, uint value) internal {
(bool success,) = to.call{value: value}(new bytes(0));
require(success, 'ACR: ETH_TRANSFER_FAILED');
}
function launchToken(
string memory name,
string memory symbol,
uint8 decimals,
uint256 totalSupply,
uint256 liquidityAmount,
address pairedToken,
uint256 pairedTokenAmount
) external returns (address token, address pair) {
token = address(new ERC20Token(
name,
symbol,
decimals,
totalSupply,
msg.sender
));
pair = IUniswapV2Factory(factory).createPair(token, pairedToken);
_safeTransferFrom(token, msg.sender, pair, liquidityAmount);
_safeTransferFrom(pairedToken, msg.sender, pair, pairedTokenAmount);
return (token, pair);
}
function launchNFTCollection(
string memory name,
string memory symbol,
string memory baseTokenURI
) external returns (address) {
return address(new ERC721Token(
name,
symbol,
baseTokenURI
));
}
}