1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 189 190 191 192 193 194 195 196 197 198 199 200 201 202 203 204 205 206 207 208 209 210 211 212 213 214 215 216 217 218 219 220 221 222 223 224 225 226 227 228 229 230 231 232 233 234 235
| //contracts/Setup.sol // SPDX-License-Identifier: MIT //token:v4.local.jna1mC3KpnBM0-XmlLS_MA4nZa1OdlHZmZyRqzA1MGdTGqZJtdC8_J63VcaYekeQkPitoKQD9Zcvdt3BKNdkHgvIUbMlo5BoQBC232lUmYuq3O_yozPI6Ks37A-vcTYs83eO1mRVp_igX3p-wd4bKXmS7Gsj_GRdNdwWAzaJSMyF7A.U2V0dXA //contract address: 0x854026c2fAB17E3e3240fA2D1cf62E4ef959ada6 pragma solidity ^0.8.0;
import {SimpleDEX} from "./DEX.sol"; import {IToken} from "./IToken.sol";
contract Setup { SimpleDEX public dex; address public profitReceiver = 0x0000000000000000000000000000000000000001; IToken public USDT; //代币 IToken public DLNU; //代币 IToken public RWEB; //代币
constructor() { dex = new SimpleDEX();
USDT = new IToken("Tether USD", "USDT", address(this)); DLNU = new IToken("VN Coin", "DLNU", address(this)); RWEB = new IToken("WM Coin", "RWEB", address(this));
USDT.approve(address(dex), type(uint256).max); //无限授权 DLNU.approve(address(dex), type(uint256).max); //无限授权 RWEB.approve(address(dex), type(uint256).max); //无限授权
dex.createLiquidityPool(address(USDT), address(DLNU)); //创建流动性池 dex.addLiquidity(0, 10000 ether, 100_000 ether); //添加流动性 dex.createLiquidityPool(address(DLNU), address(RWEB)); //创建流动性池 dex.addLiquidity(1, 100_000 ether, 100_000 ether); //添加流动性 dex.createLiquidityPool(address(USDT), address(RWEB)); //创建流动性池 dex.addLiquidity(2, 10_000 ether, 10_000 ether); //添加流动性 uint256 restUSDT = USDT.balanceOf(address(this)); //余额 USDT.approve(address(dex), restUSDT); //授权 dex.addLoan(restUSDT, address(USDT)); //添加贷款 uint256 restDLNU = DLNU.balanceOf(address(this)); //余额 DLNU.approve(address(dex), restDLNU); //授权 dex.addLoan(restDLNU, address(DLNU)); //添加贷款 uint256 restRWEB = RWEB.balanceOf(address(this)); //余额 RWEB.approve(address(dex), restRWEB); //授权 dex.addLoan(restRWEB, address(RWEB)); //添加贷款 }
function isSolved() external view returns (bool) { return USDT.balanceOf(profitReceiver) >= 100 ether; } //是否解决 } //contracts/DEX.sol // SPDX-License-Identifier: MIT pragma solidity ^0.8.0;
import "./lib/ReentrancyGuard.sol"; import "./IToken.sol";
contract SimpleDEX is ReentrancyGuard { struct AMM { IToken token0; IToken token1; uint256 reserve0; //储备0 uint256 reserve1; //储备1 mapping(address => uint256) lpBalances0; //流动性提供者余额0 mapping(address => uint256) lpBalances1; //流动性提供者余额1 } //资金池
AMM[] public amms; //资金池
event FlashLoan(address indexed borrower, uint256 amount); //闪电贷事件
constructor() {}
function addAMM(address _token0, address _token1) external { require(_token0 != _token1, "Tokens must be different");
amms.push(); //添加 uint256 index = amms.length - 1; //索引 AMM storage amm = amms[index]; //资金池
amm.token0 = IToken(_token0); amm.token1 = IToken(_token1); amm.reserve0 = 0; amm.reserve1 = 0; } //添加资金池
function createLiquidityPool(address _token0, address _token1) external { require(_token0 != _token1, "Tokens must be different"); //代币必须不同
amms.push(); uint256 index = amms.length - 1; AMM storage amm = amms[index];
amm.token0 = IToken(_token0); amm.token1 = IToken(_token1); amm.reserve0 = 0; amm.reserve1 = 0; } //创建流动性池
function addLiquidity( uint256 ammIndex, uint256 amount0, uint256 amount1 ) external { AMM storage amm = amms[ammIndex]; require( amm.token0.transferFrom(msg.sender, address(this), amount0), "Transfer of token0 failed" ); //调用者向合约转账 require( amm.token1.transferFrom(msg.sender, address(this), amount1), "Transfer of token1 failed" ); //调用者向合约转账
amm.reserve0 += amount0; amm.reserve1 += amount1; amm.lpBalances0[msg.sender] += amount0; amm.lpBalances1[msg.sender] += amount1; } //添加流动性
function removeLiquidity(uint256 ammIndex, uint256 lpAmount) external { AMM storage amm = amms[ammIndex]; uint256 amount0 = (lpAmount * amm.lpBalances0[msg.sender]) / 100; //计算 uint256 amount1 = (lpAmount * amm.lpBalances1[msg.sender]) / 100; //计算 require( amm.token0.transfer(msg.sender, amount0), "Transfer of token0 failed" ); //向调用者转账 require( amm.token1.transfer(msg.sender, amount1), "Transfer of token1 failed" ); //向调用者转账
amm.reserve0 -= amount0; //减少储备0 amm.reserve1 -= amount1; //减少储备1 amm.lpBalances0[msg.sender] -= amount0; //减少流动性 amm.lpBalances1[msg.sender] -= amount1; //减少流动性 } //移除流动性
function getPrice(uint256 ammIndex) external view returns (uint256) { AMM storage amm = amms[ammIndex];
require(amm.reserve1 > 0, "Insufficient liquidity"); //流动性不足 return amm.reserve0 / amm.reserve1; //返回兑换比例 储备0/储备1 } //获取价格
function swap(uint256 ammIndex, uint256 amountIn, bool isToken0) external { AMM storage amm = amms[ammIndex];
uint256 reserveIn = isToken0 ? amm.reserve0 : amm.reserve1; //判断谁是输入 uint256 reserveOut = isToken0 ? amm.reserve1 : amm.reserve0; //判断谁是输出
uint256 amountOut = getAmountOut(amountIn, reserveIn, reserveOut); //通过计算兑换比例获取输出金额
if (isToken0) { require( amm.token0.transferFrom(msg.sender, address(this), amountIn), "Transfer of token0 failed" ); require( amm.token1.transfer(msg.sender, amountOut), "Transfer of token1 failed" ); amm.reserve0 += amountIn; amm.reserve1 -= amountOut; } else { require( amm.token1.transferFrom(msg.sender, address(this), amountIn), "Transfer of token1 failed" ); require( amm.token0.transfer(msg.sender, amountOut), "Transfer of token0 failed" ); amm.reserve1 += amountIn; amm.reserve0 -= amountOut; } } //交换
function addLoan(uint256 amount, address token) external { require( IToken(token).transferFrom(msg.sender, address(this), amount), "Transfer of tokens failed" ); } //添加贷款
function flashLoan(uint256 amount, address token) external nonReentrant { emit FlashLoan(msg.sender, amount); require( IToken(token).balanceOf(address(this)) >= amount, "Not enough tokens in pool" );
IToken(token).transfer(msg.sender, amount); (bool success, ) = msg.sender.call( abi.encodeWithSignature( "executeOperation(uint256,address)", amount, token ) ); require(success, "Callback failed");
require( IToken(token).transferFrom(msg.sender, address(this), amount), "Transfer of tokens failed" );
emit FlashLoan(msg.sender, amount); } //闪电贷
function getAmountOut( uint256 amountIn, uint256 reserveIn, uint256 reserveOut ) internal pure returns (uint256) { require(amountIn > 0, "Insufficient input amount"); require(reserveIn > 0 && reserveOut > 0, "Insufficient liquidity"); uint256 amountInWithFee = amountIn * 1000; uint256 numerator = amountInWithFee * reserveOut; uint256 denominator = reserveIn * 1000 + amountInWithFee; return numerator / denominator; } //获取输出金额 //流入token*1000*交易池输出token数量/(交易池输入*1000+流入token*1000) } //contracts/IToken.sol // SPDX-License-Identifier: MIT pragma solidity ^0.8.0;
import "./lib/ERC20.sol";
contract IToken is ERC20 { constructor(string memory name, string memory symbol, address owner) ERC20(name, symbol) { _mint(owner, 1e30); } }
|