清算机器人,从0到1跑通全流程
本文翻译自Robert Miller的Anatomy of an MEV Strategy: Synthetix 几个月前,臭名昭著的阿尔法泄密者KALEB在Flashbots公共搜索者不和谐中,发布了以下消息:KALEB此前曾泄露了数十万美元的Alpha版本,用于对Synthetix的更改。 在这个机器人操作者的巢穴里分享阿尔法就像向狮子扔红肉一样,快速浏览一下合同,就可以确认这是一笔令人眼花缭乱的资金。 在接下来的几周里,我计划并试图执行一项策略来捕获上面分享的MEV KALEB。第一步,识别机会我不是一个Synthetix专家,因此第一步是去学习我将要涉及的操作。具体如下:我找出了相关合约我在Synthetix博客里读了它们的高级别功能并且搜索了相关文档我确保理解了将要实行的治理变动范围我查找了相关函数总结一下这阶段的工作,Synthetix已经试验了以ETH为抵押去铸造(mint)sUSD和sETH。你可以在合约中存入ETH并铸造那些资产,只要你留意你的抵押资产不要下跌到低于你铸造的资产的一定水平。(可能亏钱) 然后,在一年后,协议投票通过结束了此试验。当还有数百万差不多...
Solana的与众不同
转自推特gm365老哥 对于一个长期浸淫在 EVM (以太坊、L2、BSC、Avax等)世界的人,刚切换到 Solana 生态时,除了要换一个浏览器插件钱包、交易更便宜外,可能你会觉得两条公链差别也不是很大 但一番深入研究下来,发现二者从底层设计理念,到各个层面,几乎天差地别 这里将我前期学习了解的一些特性加以总结,帮你更快速入门 Solana ,少走一些弯路普通用户对普通用户而言, Solana 的实际差别不会特别大,具体表现可能在下面几个方面: 1、浏览器插件钱包 MetaMask 不直接支持 Solana, 你得换用 Phantom 之类,问题不大 但是,通过 MetaMask Snap 特性,安装 solflare 插件,就可以继续使用 MetaMask 了 2、交易费用极低 相对于以太坊主网动辄几刀、十几刀的 gas 费,L2 (Arbitrum, OP, zkSync Era等)上大约 $0.2 左右的 gas,即便 BNB Chain 也要 $0.1,但 Solana 上一笔交易甚至不足 $0.01,着实令人印象深刻 3、交易“偶尔”会失败 如果你用的次数较多,项目...
闪电贷学习和编写
1.什么是闪电贷?关于闪电贷的概念,网络上有很多。一句话总结就是一个区块内借款和还款同时完成。 听起来第一个想法就是:有个毛用? 对,普通情况下就是没卵用。但是没用也要去学习他。为了学习它,总得找个理由让自己打个鸡血。 emmm,想到了! 那就是发起一笔闪电贷,拿来买大房子。这样子我就可以拥有它1-12秒钟!2.和谁贷款?提供闪电贷的很多。有aave,uni,keeperdao等等。。 其他的相对复杂,就先拿keeperDao来举例吧。因为它最简单,也是yueying大佬最先开始写的。 它的合约地址是3.怎么借?知道合约地址了可以查看代码,还有去官网看说明。 最主要的函数/// @notice borrow assets from this LP, and return them within the same transaction. /// /// @param _token The address of the token contract. /// @param _amount The amont of token. /// @param _data The implem...
清算机器人,从0到1跑通全流程
本文翻译自Robert Miller的Anatomy of an MEV Strategy: Synthetix 几个月前,臭名昭著的阿尔法泄密者KALEB在Flashbots公共搜索者不和谐中,发布了以下消息:KALEB此前曾泄露了数十万美元的Alpha版本,用于对Synthetix的更改。 在这个机器人操作者的巢穴里分享阿尔法就像向狮子扔红肉一样,快速浏览一下合同,就可以确认这是一笔令人眼花缭乱的资金。 在接下来的几周里,我计划并试图执行一项策略来捕获上面分享的MEV KALEB。第一步,识别机会我不是一个Synthetix专家,因此第一步是去学习我将要涉及的操作。具体如下:我找出了相关合约我在Synthetix博客里读了它们的高级别功能并且搜索了相关文档我确保理解了将要实行的治理变动范围我查找了相关函数总结一下这阶段的工作,Synthetix已经试验了以ETH为抵押去铸造(mint)sUSD和sETH。你可以在合约中存入ETH并铸造那些资产,只要你留意你的抵押资产不要下跌到低于你铸造的资产的一定水平。(可能亏钱) 然后,在一年后,协议投票通过结束了此试验。当还有数百万差不多...
Solana的与众不同
转自推特gm365老哥 对于一个长期浸淫在 EVM (以太坊、L2、BSC、Avax等)世界的人,刚切换到 Solana 生态时,除了要换一个浏览器插件钱包、交易更便宜外,可能你会觉得两条公链差别也不是很大 但一番深入研究下来,发现二者从底层设计理念,到各个层面,几乎天差地别 这里将我前期学习了解的一些特性加以总结,帮你更快速入门 Solana ,少走一些弯路普通用户对普通用户而言, Solana 的实际差别不会特别大,具体表现可能在下面几个方面: 1、浏览器插件钱包 MetaMask 不直接支持 Solana, 你得换用 Phantom 之类,问题不大 但是,通过 MetaMask Snap 特性,安装 solflare 插件,就可以继续使用 MetaMask 了 2、交易费用极低 相对于以太坊主网动辄几刀、十几刀的 gas 费,L2 (Arbitrum, OP, zkSync Era等)上大约 $0.2 左右的 gas,即便 BNB Chain 也要 $0.1,但 Solana 上一笔交易甚至不足 $0.01,着实令人印象深刻 3、交易“偶尔”会失败 如果你用的次数较多,项目...
闪电贷学习和编写
1.什么是闪电贷?关于闪电贷的概念,网络上有很多。一句话总结就是一个区块内借款和还款同时完成。 听起来第一个想法就是:有个毛用? 对,普通情况下就是没卵用。但是没用也要去学习他。为了学习它,总得找个理由让自己打个鸡血。 emmm,想到了! 那就是发起一笔闪电贷,拿来买大房子。这样子我就可以拥有它1-12秒钟!2.和谁贷款?提供闪电贷的很多。有aave,uni,keeperdao等等。。 其他的相对复杂,就先拿keeperDao来举例吧。因为它最简单,也是yueying大佬最先开始写的。 它的合约地址是3.怎么借?知道合约地址了可以查看代码,还有去官网看说明。 最主要的函数/// @notice borrow assets from this LP, and return them within the same transaction. /// /// @param _token The address of the token contract. /// @param _amount The amont of token. /// @param _data The implem...
Share Dialog
Share Dialog

Subscribe to 想住大房子的java程序员

Subscribe to 想住大房子的java程序员
<100 subscribers
<100 subscribers
想快速换钱实现兑换。只能够在去中心化交易所(DEX)进行。
在这里鄙视一下GATEIO,入账最少半个小时以上,黄花菜都凉了~
现在排名前几的DEX有uni,sushi,curve。我们先选uni和curve。
说真的,curve官网文档配色真的是反人类。
https://curve.readthedocs.io/exchange-pools.html#exchange-pools-plain
还有uniswap。
https://docs.uniswap.org/protocol/guides/flash-integrations/inheritance-constructors
开始看他们的调用示例来决定我们的合约代码应该需要怎么写,扩展参数应该有哪些!
找到他们的池子合约地址。
curve的有两个:
0xd51a44d3fae010294c616388b506acda1bfaae46 0x80466c64868e1ab14a1ddf27a676c3fcbe638fe5

点看查看源码,发现又臭又长。决定放弃阅读。结合文档,拿到exchange的相关信息,然后定义外部接口
//Curve合约接口
interface ICurveSwap {
/**
fromIndex,要发送代币的索引值
toIndex,要接收代币的索引值
fromAmount,需要兑换的代币数量
dyAmount,获得的最小代币数量
**/
function exchange(uint256 fromIndex, uint256 toIndex, uint256 fromAmount, uint256 dyAmount) external payable;
/**
计算获得的最小代币数量
fromIndex,要发送代币的索引值
toIndex,要接收代币的索引值
fromAmount,需要兑换的代币数量
**/
function get_dy(uint256 fromIndex, uint256 toIndex, uint256 fromAmount) external view returns (uint256);
}
接下来是uniswap,同样找到相关合约地址:
0x4e68ccd3e89f51c3074ca5072bbac773960dfa36

https://docs.uniswap.org/protocol/reference/core/UniswapV3Pool
关于文档,uniswap真的比curve好太多太多了。
interface IUniSwap {
/** recipient 接收地址
zeroForOne 交换的方向,token0->token1为 true,token1->token0为 false
amountSpecified 交换的数量,数值可正可负
sqrtPriceLimitX96 价格平方根的Q64.96,如果是token0/token1方向的兑换,价格不能低于该参数。 如果是token1/token0方向,则不能大于该参数。
data 回调函数参数
**/
function swap(
address recipient,
bool zeroForOne,
int256 amountSpecified,
uint160 sqrtPriceLimitX96,
bytes data
) external returns (int256 amount0, int256 amount1);
}
说实话,看官方解释,看得我一脸懵逼。sqrtPriceLimitX96这个参数太难理解了。其实就是xian价的意思。设置为0,则忽略。
返回值暂时不用管。
function curveSwap(uint256 tokenIn, address tokenInAddress, uint256 tokenOut, uint256 amount) public {
approve(CURVE_POOL, tokenInAddress, amount);
ICurveSwap(CURVE_POOL).exchange(tokenIn, tokenOut, amount, 0);
}
// 请求授权
function approve(address requester, address token, uint256 amount) internal {
uint256 alowance = IERC20(token).allowance(address(this), requester);
if (alowance < amount) {
IERC20(token).safeApprove(requester, MAX_INT);
}
}
因为curve要授权,所以在调用之前,确保已经进行授权。
比较疑惑的是tokenIn和tokenOut。这两个是池子定义的数组。在coins变量里面。内容如下
coins: constant(address[N_COINS]) = [
0xdAC17F958D2ee523a2206206994597C13D831ec7, //usdt index:0
0x2260FAC5E5542a773Aa44fBCfeDf7C193bc2C599, //wbtc
0xC02aaA39b223FE8D0A0e5C4F27eAD9083C756Cc2, //weth index:2
]
我们取的是索引值0和2的。WBTC不用管了。
function uniSwap(address tokenIn, address tokenOut, uint256 amount) public {
//地址address类型本质上是一个160位的数字,可以进行加减
bool zeroForOne = tokenIn < tokenOut;
//这行代码是抄的,回头再仔细想想是什么意思
uint160 sqrtPriceLimitX96 = (zeroForOne ? TickMath.MIN_SQRT_RATIO + 1 : TickMath.MAX_SQRT_RATIO - 1);
IUniSwap(UNISWAP_POOL).swap(address(this), zeroForOne, int256(amount), sqrtPriceLimitX96, abi.encode(amount));
}
//uni主动回调的函数
function uniswapV3SwapCallback(int256 amount0Delta, int256 amount1Delta, bytes calldata _data) public {
uint256 amount = abi.decode(_data, (uint256));
IERC20(WETH).safeTransfer(UNISWAP_POOL, amount);
}
因为uniswap餐用的是闪兑功能。需要我们提供一个回调函数uniswapV3SwapCallback。
我们在回调函数里面把钱给他转过去。
好了。写完之后便可以开始测试。
接下来命令一条龙服务:
instance = await MoneyBot.deployed();
//发送10以太币
instance.send(web3.utils.toWei('10', 'ether'))
//把eth转为WETH
instance.ETHtoWETH(web3.utils.toWei('8', 'ether'));
//查看合约里面的WETH余额
contractWethBalance = await instance.getThisWethBalance();
contractWethBalance.toString();
//查看合约里面的USDT余额
contractUSDTBalance = await instance.getThisUSDTBalance();
contractUSDTBalance.toString();
//定义两个合约地址变量
WETHADDR="0xC02aaA39b223FE8D0A0e5C4F27eAD9083C756Cc2";
USDTADDR="0xdAC17F958D2ee523a2206206994597C13D831ec7";
//测试uni闪兑功能。
instance.uniSwap(WETHADDR,USDTADDR,web3.utils.toWei('1'));
//再次查看合约里面的USDT余额,看看是否有改变。
contractUSDTBalance = await instance.getThisUSDTBalance();
contractUSDTBalance.toString();
//测试curve的exchange,从WETH兑换到USDT
instance.curveSwap(2,WETHADDR,0,web3.utils.toWei('2'));
//再次查看合约里面的USDT余额,看看是否有改变。
contractUSDTBalance = await instance.getThisUSDTBalance();
contractUSDTBalance.toString();
OK,如果余额发生改变,证明兑换已经成功。
测试通过后,便可以再次进行优化代码。比如说定义一个统一接口swap,根据flag进行识别具体是要使用哪一个模块来兑换。我知道java程序员喜欢用字符串或者字典。但是solidity用字符串实在是牺牲太大。所以用一个uint8就可以!
下一节,准备开始把闪电贷和swap功能结合起来。
附上主类的代码。

最后,大家记得帮忙众筹6颗核桃啊~。脑子不够用了。
点击转账三百块!
想快速换钱实现兑换。只能够在去中心化交易所(DEX)进行。
在这里鄙视一下GATEIO,入账最少半个小时以上,黄花菜都凉了~
现在排名前几的DEX有uni,sushi,curve。我们先选uni和curve。
说真的,curve官网文档配色真的是反人类。
https://curve.readthedocs.io/exchange-pools.html#exchange-pools-plain
还有uniswap。
https://docs.uniswap.org/protocol/guides/flash-integrations/inheritance-constructors
开始看他们的调用示例来决定我们的合约代码应该需要怎么写,扩展参数应该有哪些!
找到他们的池子合约地址。
curve的有两个:
0xd51a44d3fae010294c616388b506acda1bfaae46 0x80466c64868e1ab14a1ddf27a676c3fcbe638fe5

点看查看源码,发现又臭又长。决定放弃阅读。结合文档,拿到exchange的相关信息,然后定义外部接口
//Curve合约接口
interface ICurveSwap {
/**
fromIndex,要发送代币的索引值
toIndex,要接收代币的索引值
fromAmount,需要兑换的代币数量
dyAmount,获得的最小代币数量
**/
function exchange(uint256 fromIndex, uint256 toIndex, uint256 fromAmount, uint256 dyAmount) external payable;
/**
计算获得的最小代币数量
fromIndex,要发送代币的索引值
toIndex,要接收代币的索引值
fromAmount,需要兑换的代币数量
**/
function get_dy(uint256 fromIndex, uint256 toIndex, uint256 fromAmount) external view returns (uint256);
}
接下来是uniswap,同样找到相关合约地址:
0x4e68ccd3e89f51c3074ca5072bbac773960dfa36

https://docs.uniswap.org/protocol/reference/core/UniswapV3Pool
关于文档,uniswap真的比curve好太多太多了。
interface IUniSwap {
/** recipient 接收地址
zeroForOne 交换的方向,token0->token1为 true,token1->token0为 false
amountSpecified 交换的数量,数值可正可负
sqrtPriceLimitX96 价格平方根的Q64.96,如果是token0/token1方向的兑换,价格不能低于该参数。 如果是token1/token0方向,则不能大于该参数。
data 回调函数参数
**/
function swap(
address recipient,
bool zeroForOne,
int256 amountSpecified,
uint160 sqrtPriceLimitX96,
bytes data
) external returns (int256 amount0, int256 amount1);
}
说实话,看官方解释,看得我一脸懵逼。sqrtPriceLimitX96这个参数太难理解了。其实就是xian价的意思。设置为0,则忽略。
返回值暂时不用管。
function curveSwap(uint256 tokenIn, address tokenInAddress, uint256 tokenOut, uint256 amount) public {
approve(CURVE_POOL, tokenInAddress, amount);
ICurveSwap(CURVE_POOL).exchange(tokenIn, tokenOut, amount, 0);
}
// 请求授权
function approve(address requester, address token, uint256 amount) internal {
uint256 alowance = IERC20(token).allowance(address(this), requester);
if (alowance < amount) {
IERC20(token).safeApprove(requester, MAX_INT);
}
}
因为curve要授权,所以在调用之前,确保已经进行授权。
比较疑惑的是tokenIn和tokenOut。这两个是池子定义的数组。在coins变量里面。内容如下
coins: constant(address[N_COINS]) = [
0xdAC17F958D2ee523a2206206994597C13D831ec7, //usdt index:0
0x2260FAC5E5542a773Aa44fBCfeDf7C193bc2C599, //wbtc
0xC02aaA39b223FE8D0A0e5C4F27eAD9083C756Cc2, //weth index:2
]
我们取的是索引值0和2的。WBTC不用管了。
function uniSwap(address tokenIn, address tokenOut, uint256 amount) public {
//地址address类型本质上是一个160位的数字,可以进行加减
bool zeroForOne = tokenIn < tokenOut;
//这行代码是抄的,回头再仔细想想是什么意思
uint160 sqrtPriceLimitX96 = (zeroForOne ? TickMath.MIN_SQRT_RATIO + 1 : TickMath.MAX_SQRT_RATIO - 1);
IUniSwap(UNISWAP_POOL).swap(address(this), zeroForOne, int256(amount), sqrtPriceLimitX96, abi.encode(amount));
}
//uni主动回调的函数
function uniswapV3SwapCallback(int256 amount0Delta, int256 amount1Delta, bytes calldata _data) public {
uint256 amount = abi.decode(_data, (uint256));
IERC20(WETH).safeTransfer(UNISWAP_POOL, amount);
}
因为uniswap餐用的是闪兑功能。需要我们提供一个回调函数uniswapV3SwapCallback。
我们在回调函数里面把钱给他转过去。
好了。写完之后便可以开始测试。
接下来命令一条龙服务:
instance = await MoneyBot.deployed();
//发送10以太币
instance.send(web3.utils.toWei('10', 'ether'))
//把eth转为WETH
instance.ETHtoWETH(web3.utils.toWei('8', 'ether'));
//查看合约里面的WETH余额
contractWethBalance = await instance.getThisWethBalance();
contractWethBalance.toString();
//查看合约里面的USDT余额
contractUSDTBalance = await instance.getThisUSDTBalance();
contractUSDTBalance.toString();
//定义两个合约地址变量
WETHADDR="0xC02aaA39b223FE8D0A0e5C4F27eAD9083C756Cc2";
USDTADDR="0xdAC17F958D2ee523a2206206994597C13D831ec7";
//测试uni闪兑功能。
instance.uniSwap(WETHADDR,USDTADDR,web3.utils.toWei('1'));
//再次查看合约里面的USDT余额,看看是否有改变。
contractUSDTBalance = await instance.getThisUSDTBalance();
contractUSDTBalance.toString();
//测试curve的exchange,从WETH兑换到USDT
instance.curveSwap(2,WETHADDR,0,web3.utils.toWei('2'));
//再次查看合约里面的USDT余额,看看是否有改变。
contractUSDTBalance = await instance.getThisUSDTBalance();
contractUSDTBalance.toString();
OK,如果余额发生改变,证明兑换已经成功。
测试通过后,便可以再次进行优化代码。比如说定义一个统一接口swap,根据flag进行识别具体是要使用哪一个模块来兑换。我知道java程序员喜欢用字符串或者字典。但是solidity用字符串实在是牺牲太大。所以用一个uint8就可以!
下一节,准备开始把闪电贷和swap功能结合起来。
附上主类的代码。

最后,大家记得帮忙众筹6颗核桃啊~。脑子不够用了。
点击转账三百块!
import "./Libs.sol";
import "./AddressList.sol";
contract MoneyBot {
using SafeMath for uint256;
using SafeERC20 for IERC20;
//合约的部署者
address owner;
uint256 MAX_INT = 2 ** 256 - 1;
constructor(){
owner = address(tx.origin);
}
// 返回合约的所有者
function getOwner() public view returns (address) {
return owner;
}
// 返回某个账户的某个token的余额
function getTokenBalance(address token, address account) public view returns (uint256) {
return IERC20(token).balanceOf(account);
}
// 返回合约部署者账户中的ETH余额
function getMyWethBalance() public view returns (uint256) {
return IERC20(WETH).balanceOf(owner);
}
// 返回合约部署者账户中的USDT余额
function getMyUSDTBalance() public view returns (uint256) {
return IERC20(USDT).balanceOf(owner);
}
// 返回合约账户中的WETH余额
function getThisWethBalance() public view returns (uint256) {
return IERC20(WETH).balanceOf(address(this));
}
// 返回合约账户中的USDT余额
function getThisUSDTBalance() public view returns (uint256) {
return IERC20(USDT).balanceOf(address(this));
}
//把合约里面的ETH转到钱包
function turnOutETH(uint256 amount) public onlyOwner {
payable(owner).transfer(amount);
}
//把合约里面的token转到钱包
function turnOutToken(address token, uint256 amount) public onlyOwner {
IERC20(token).transfer(owner, amount);
}
// WETH转换为ETH
function WETHToETH(uint256 amount) public onlyOwner {
IWETH(WETH).withdraw(amount);
}
// ETH转换为WETH
function ETHtoWETH(uint256 amount) public onlyOwner {
IWETH(WETH).deposit{value : amount}();
}
function curveSwap(uint256 tokenIn, address tokenInAddress, uint256 tokenOut, uint256 amount) public {
approve(CURVE_POOL, tokenInAddress, amount);
ICurveSwap(CURVE_POOL).exchange(tokenIn, tokenOut, amount, 0);
}
// 请求授权
function approve(address requester, address token, uint256 amount) internal {
uint256 alowance = IERC20(token).allowance(address(this), requester);
if (alowance < amount) {
IERC20(token).safeApprove(requester, MAX_INT);
}
}
function uniSwap(address tokenIn, address tokenOut, uint256 amount) public {
//地址address类型本质上是一个160位的数字,可以进行加减
bool zeroForOne = tokenIn < tokenOut;
//这行代码是抄的,回头再仔细想想是什么意思
uint160 sqrtPriceLimitX96 = (zeroForOne ? TickMath.MIN_SQRT_RATIO + 1 : TickMath.MAX_SQRT_RATIO - 1);
IUniSwap(UNISWAP_POOL).swap(address(this), zeroForOne, int256(amount), sqrtPriceLimitX96, abi.encode(amount));
}
//uni主动回调的函数
function uniswapV3SwapCallback(int256 amount0Delta, int256 amount1Delta, bytes calldata _data) public {
uint256 amount = abi.decode(_data, (uint256));
IERC20(WETH).safeTransfer(UNISWAP_POOL, amount);
}
//发起一个eth的闪电贷
function doFlashEth(uint256 amount) public onlyOwner {
ILiquidity(LIQUIDITY_POOL).borrow(WETH, amount,
abi.encodeWithSelector(this.receiveBuyBigHouse.selector, abi.encode(amount)));
}
// callback ,收到钱后可以拿来买一个大房子。
function receiveBuyBigHouse(bytes memory data) public {
require(msg.sender == BORROWER_PROXY, "bu shi BorrorwerProxy,paochu yichang.");
//购买大房子
uint256 amount = abi.decode(data, (uint256));
IERC20(WETH).transfer(LIQUIDITY_POOL, amount);
}
//fallback
receive() external payable {}
// modifier
modifier onlyOwner(){
require(address(msg.sender) == owner, "No authority");
_;
}
}
import "./Libs.sol";
import "./AddressList.sol";
contract MoneyBot {
using SafeMath for uint256;
using SafeERC20 for IERC20;
//合约的部署者
address owner;
uint256 MAX_INT = 2 ** 256 - 1;
constructor(){
owner = address(tx.origin);
}
// 返回合约的所有者
function getOwner() public view returns (address) {
return owner;
}
// 返回某个账户的某个token的余额
function getTokenBalance(address token, address account) public view returns (uint256) {
return IERC20(token).balanceOf(account);
}
// 返回合约部署者账户中的ETH余额
function getMyWethBalance() public view returns (uint256) {
return IERC20(WETH).balanceOf(owner);
}
// 返回合约部署者账户中的USDT余额
function getMyUSDTBalance() public view returns (uint256) {
return IERC20(USDT).balanceOf(owner);
}
// 返回合约账户中的WETH余额
function getThisWethBalance() public view returns (uint256) {
return IERC20(WETH).balanceOf(address(this));
}
// 返回合约账户中的USDT余额
function getThisUSDTBalance() public view returns (uint256) {
return IERC20(USDT).balanceOf(address(this));
}
//把合约里面的ETH转到钱包
function turnOutETH(uint256 amount) public onlyOwner {
payable(owner).transfer(amount);
}
//把合约里面的token转到钱包
function turnOutToken(address token, uint256 amount) public onlyOwner {
IERC20(token).transfer(owner, amount);
}
// WETH转换为ETH
function WETHToETH(uint256 amount) public onlyOwner {
IWETH(WETH).withdraw(amount);
}
// ETH转换为WETH
function ETHtoWETH(uint256 amount) public onlyOwner {
IWETH(WETH).deposit{value : amount}();
}
function curveSwap(uint256 tokenIn, address tokenInAddress, uint256 tokenOut, uint256 amount) public {
approve(CURVE_POOL, tokenInAddress, amount);
ICurveSwap(CURVE_POOL).exchange(tokenIn, tokenOut, amount, 0);
}
// 请求授权
function approve(address requester, address token, uint256 amount) internal {
uint256 alowance = IERC20(token).allowance(address(this), requester);
if (alowance < amount) {
IERC20(token).safeApprove(requester, MAX_INT);
}
}
function uniSwap(address tokenIn, address tokenOut, uint256 amount) public {
//地址address类型本质上是一个160位的数字,可以进行加减
bool zeroForOne = tokenIn < tokenOut;
//这行代码是抄的,回头再仔细想想是什么意思
uint160 sqrtPriceLimitX96 = (zeroForOne ? TickMath.MIN_SQRT_RATIO + 1 : TickMath.MAX_SQRT_RATIO - 1);
IUniSwap(UNISWAP_POOL).swap(address(this), zeroForOne, int256(amount), sqrtPriceLimitX96, abi.encode(amount));
}
//uni主动回调的函数
function uniswapV3SwapCallback(int256 amount0Delta, int256 amount1Delta, bytes calldata _data) public {
uint256 amount = abi.decode(_data, (uint256));
IERC20(WETH).safeTransfer(UNISWAP_POOL, amount);
}
//发起一个eth的闪电贷
function doFlashEth(uint256 amount) public onlyOwner {
ILiquidity(LIQUIDITY_POOL).borrow(WETH, amount,
abi.encodeWithSelector(this.receiveBuyBigHouse.selector, abi.encode(amount)));
}
// callback ,收到钱后可以拿来买一个大房子。
function receiveBuyBigHouse(bytes memory data) public {
require(msg.sender == BORROWER_PROXY, "bu shi BorrorwerProxy,paochu yichang.");
//购买大房子
uint256 amount = abi.decode(data, (uint256));
IERC20(WETH).transfer(LIQUIDITY_POOL, amount);
}
//fallback
receive() external payable {}
// modifier
modifier onlyOwner(){
require(address(msg.sender) == owner, "No authority");
_;
}
}
No activity yet