什么是DApp?
去中心化应用(DApp)是一种大部分或完全分散化的应用。考虑一个应用程序是否是去中心化的应用主要方面包括:前端软件、后端软件(应用逻辑)、数据存储、命名解析、信息通信等。其中每一个都可以有些集中化,也可以有些分散化。例如,前端可以开发成在集中式服务器上运行的网络应用,或者开发成在设备上运行的移动应用。后端和存储可以是在私人服务器和专有数据库上,或者是智能合约和P2P存储。
创建一个DApp有很多典型的中心化架构无法提供的优势,其中包括:
1)弹性:通过由智能合约控制业务逻辑,DApp后端将完全分布在区块链平台上进行管理。与在中心化服务器上部署应用不同,只要平台还在运行,DApp就不会有停机,并将继续可用。
2)透明度:DApp的链上特性让每个人都可以检查代码,更加容易确认其功能。与DApp的任何交互都将永远存储在区块链中。
3)防篡改:用户将始终能够与DApp交互,而不受任何中心化控制的干扰。一旦代码部署在网络上,任何服务提供商,甚至是智能合约的所有者都不能改变代码。
外部函数(仅供合约外部调用)
swapExactTokensForTokens
代码速浏览
function swapExactTokensForTokens(
uint amountIn,
uint amountOutMin,
address[]calldata path,
address to,
uint deadline
)external virtual override ensure(deadline)returns(uint[]memory amounts){
amounts=UniswapV2Library.getAmountsOut(factory,amountIn,path);
require(amounts[amounts.length-1]>=amountOutMin,'UniswapV2Router:INSUFFICIENT_OUTPUT_AMOUNT');
TransferHelper.safeTransferFrom(
path[0],msg.sender,UniswapV2Library.pairFor(factory,path[0],path[1]),amounts[0]
);
_swap(amounts,path,to);
}
参数分析
函数swapExactTokensForTokens的入参有5个,出参有1个,对应的解释如下:
function swapExactTokensForTokens(
uint amountIn,//交易支付代币数量
uint amountOutMin,//交易获得代币最小值
address[]calldata path,//交易路径列表
address to,//交易获得的token发送到的地址
uint deadline//过期时间
)external virtual override ensure(deadline)returns(
uint[]memory amounts//交易期望数量列表
){
...
函数swapExactTokensForTokens实现了用户使用数量精确的tokenA交易数量不精确的tokenB的流程。用户使用确定的amountIn数量的tokenA,交易获得tokenB的数量不会小于amountOutMin,但具体tokenB的数量只有交易完成之后才能知道。这同样是由于区块链上交易不是实时的,实际交易和预期交易相比会有一定的偏移。
实现分析
...
//检查交易是否过期
ensure(deadline)
{
//获取path列表下,支付amountIn数量的path[0]代币,各个代币交易的预期数量
amounts=UniswapV2Library.getAmountsOut(factory,amountIn,path);
//如果最终获得的代币数量小于amountOutMin,则交易失败
require(amounts[amounts.length-1]>=amountOutMin,'UniswapV2Router:INSUFFICIENT_OUTPUT_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,to);
代码速浏览
function swapTokensForExactTokens(
uint amountOut,
uint amountInMax,
address[]calldata path,
address to,
uint deadline
)external virtual override ensure(deadline)returns(uint[]memory amounts){
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,to);
参数分析
函数swapTokensForExactTokens的入参有5个,出参有1个,对应的解释如下:
function swapTokensForExactTokens(
uint amountOut,//交易获得的代币数量
uint amountInMax,//交易支付代币的最多数量
address[]calldata path,//交易路径列表
address to,//交易获得的token发送到的地址
uint deadline//过期时间
)external virtual override ensure(deadline)returns(
uint[]memory amounts//交易期望数量列表
){
函数swapTokensForExactTokens实现了用户使用数量不精确的tokenA交易数量精确的tokenB的流程。用户会使用数量不大于amountInMax数量的tokenA,交易获得amountOut数量的tokenB。
实现分析
...
//检查交易是否过期
ensure(deadline)
{
//获取path列表下,获得amountIn数量的path[path.length-1]代币,各个代币交易的预期数量
amounts=UniswapV2Library.getAmountsIn(factory,amountOut,path);
//如果path[0]代币数量大于amountInMax,则交易失败
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,to);
}