基于区块链的数字藏品具备唯一性、不可分割、不可篡改、可验证、稀缺性等技术特性:
(1)唯一性:每个数字藏品在特定链上都具备唯一标识,可以代表数字或现实世界中的某个资产对象。
(2)不可分割:每个数字藏品自身都不可分割,可代表特定的数字藏品。
(3)不可篡改:基于区块链不可篡改的特性,使得数字藏品本身属性及所有权信息、历史交易记录等信息在抗篡改的链式数据结构中存储记录。
(4)可验证:区块链上信息公开透明,所有用户均可查询、验证数字藏品的所有权信息。
(5)稀缺性:互联网时代,信息复制门槛低,价值难受到认可。而区块链数字藏品独一无二、权属明确,可永久保存,具备稀缺性,让基于区块链的数字藏品有更强的溢价能力。
wapExactETHForTokens
代码速浏览
function swapExactETHForTokens(uint amountOutMin,address[]calldata path,address to,uint deadline)
external
virtual
override
payable
ensure(deadline)
returns(uint[]memory amounts)
{
require(path[0]==WETH,'UniswapV2Router:INVALID_PATH');
amounts=UniswapV2Library.getAmountsOut(factory,msg.value,path);
require(amounts[amounts.length-1]>=amountOutMin,'UniswapV2Router:INSUFFICIENT_OUTPUT_AMOUNT');
IWETH(WETH).deposit{value:amounts[0]}();
assert(IWETH(WETH).transfer(UniswapV2Library.pairFor(factory,path[0],path[1]),amounts[0]));
_swap(amounts,path,to);
}
参数分析
函数swapExactETHForTokens的入参有4个,出参有1个,对应的解释如下:
function swapExactETHForTokens(
uint amountOutMin,//交易获得代币最小值
address[]calldata path,//交易路径列表
address to,//交易获得的token发送到的地址
uint deadline//过期时间
)external virtual override payable ensure(deadline)returns(
uint[]memory amounts//交易期望数量列表
){
函数swapExactETHForTokens和函数swapExactTokensForTokens的逻辑几乎一样,只是把支付精确数量的token换成了支付精确数量的ETH。因此多了一些和ETH相关的额外操作。
实现分析
...
//检查交易是否过期
ensure(deadline)
{
//检查path[0]是否为WETH地址
require(path[0]==WETH,'UniswapV2Router:INVALID_PATH');
//获取path列表下,支付amountIn数量的path[0]代币,各个代币交易的预期数量
amounts=UniswapV2Library.getAmountsOut(factory,msg.value,path);
//如果最终获得的代币数量小于amountOutMin,则交易失败
require(amounts[amounts.length-1]>=amountOutMin,'UniswapV2Router:INSUFFICIENT_OUTPUT_AMOUNT');
//把用户支付的ETH换成WETH
IWETH(WETH).deposit{value:amounts[0]}();
//将amounts[0]数量的WETH代币从Router中转移到path[0],path[1]的流动池
assert(IWETH(WETH).transfer(UniswapV2Library.pairFor(factory,path[0],path[1]),amounts[0]));
//按path列表执行交易集合
_swap(amounts,path,to);
总结
此函数一般用于出售确定数量的ETH,获得不确定数量代币。
swapTokensForExactETH
代码速浏览
function swapTokensForExactETH(uint amountOut,uint amountInMax,address[]calldata path,address to,uint deadline)
external
virtual
override
ensure(deadline)
returns(uint[]memory amounts)
{
require(path[path.length-1]==WETH,'UniswapV2Router:INVALID_PATH');
amounts=UniswapV2Library.getAmountsIn(factory,amountOut,path);
require(amounts[0]<=amountInMax,'UniswapV2Router:EXCESSIVE_INPUT_AMOUNT');
TransferHelper.safeTransferFrom(
path[0],msg.sender,UniswapV2Library.pairFor(factory,path[0],path[1]),amounts[0]
);
_swap(amounts,path,address(this));
IWETH(WETH).withdraw(amounts[amounts.length-1]);
TransferHelper.safeTransferETH(to,amounts[amounts.length-1]);
参数分析
函数swapTokensForExactETH的入参有5个,出参有1个,对应的解释如下:
function swapTokensForExactETH(
uint amountOut,//交易获得的代币数量
uint amountInMax,//交易支付代币的最多数量
address[]calldata path,//交易路径列表
address to,//交易获得的token发送到的地址
uint deadline//过期时间
)external virtual override ensure(deadline)returns(
uint[]memory amounts//交易期望数量列表
){
函数swapTokensForExactETH和函数swapExactETHForTokens相比,仅交换了一下代币的交易顺序,执行逻辑还是差不多的。
实现分析
...
//检查交易是否过期
ensure(deadline)
{
//检查path[path.length-1]是否为WETH地址
require(path[path.length-1]==WETH,'UniswapV2Router:INVALID_PATH');
//获取path列表下,获得amountOut数量的path[path.length-1]代币,各个代币交易的预期数量
amounts=UniswapV2Library.getAmountsIn(factory,amountOut,path);
//如果最终获得的代币数量小于amountOutMin,则交易失败
require(amounts[0]<=amountInMax,'UniswapV2Router:EXCESSIVE_INPUT_AMOUNT');
//将amounts[0]数量的path[0]代币从用户账户中转移到path[0],path[1]的流动池
TransferHelper.safeTransferFrom(
path[0],msg.sender,UniswapV2Library.pairFor(factory,path[0],path[1]),amounts[0]
);
//按path列表执行交易集合
_swap(amounts,path,address(this));
//将WETH换成ETH
IWETH(WETH).withdraw(amounts[amounts.length-1]);
//把ETH发送给to地址
TransferHelper.safeTransferETH(to,amounts[amounts.length-1]);