Web3.0:指移动互联网后下一阶段的互联网生态,主要通过区块链等技术手段实现去中心化的网络形式,实现可以模拟现实世界感受,能够打破虚拟与现实边界的互联网。
Web1.0→Web2.0→Web3.0
Web1.0是Web的“可读取”阶段,用户之间的互动是有限的,就像早期的桌面网页;
Web2.0是Web的“可交互”阶段,用户可以与网站或其他人进行交互和互动,就是如今的社交网络、移动网络、云计算等;
Web3.0是网络的“可执行”阶段,计算机可以像人类一样解释信息,然后为用户生成个性化内容,如今正在大力发展的人工智能、边缘计算等。
UniswapV2ERC20解析
UniswapV2ERC20的接口实现合约如下:
contract UniswapV2ERC20 is IUniswapV2ERC20{
using SafeMath for uint;
string public constant name='Uniswap V2';
string public constant symbol='UNI-V2';
uint8 public constant decimals=18;
uint public totalSupply;
mapping(address=>uint)public balanceOf;
mapping(address=>mapping(address=>uint))public allowance;
bytes32 public DOMAIN_SEPARATOR;
//keccak256("Permit(address owner,address spender,uint256 value,uint256 nonce,uint256 deadline)");
bytes32 public constant PERMIT_TYPEHASH=0x6e71edae12b1b97f4d1f60370fef10105fa2faae0126114a169c64845d6126c9;
mapping(address=>uint)public nonces;
event Approval(address indexed owner,address indexed spender,uint value);
event Transfer(address indexed from,address indexed to,uint value);
constructor()public{
uint chainId;
assembly{
chainId:=chainid
}
DOMAIN_SEPARATOR=keccak256(
abi.encode(
keccak256('EIP712Domain(string name,string version,uint256 chainId,address verifyingContract)'),
keccak256(bytes(name)),
keccak256(bytes('1')),
chainId,
address(this)
)
);
}
function _mint(address to,uint value)internal{
totalSupply=totalSupply.add(value);
balanceOf[to]=balanceOf[to].add(value);
emit Transfer(address(0),to,value);
}
function _burn(address from,uint value)internal{
balanceOf[from]=balanceOf[from].sub(value);
totalSupply=totalSupply.sub(value);
emit Transfer(from,address(0),value);
}
function _approve(address owner,address spender,uint value)private{
allowanceowner=value;
emit Approval(owner,spender,value);
}
function _transfer(address from,address to,uint value)private{
balanceOf[from]=balanceOf[from].sub(value);
balanceOf[to]=balanceOf[to].add(value);
emit Transfer(from,to,value);
}
function approve(address spender,uint value)external returns(bool){
_approve(msg.sender,spender,value);
return true;
}
function transfer(address to,uint value)external returns(bool){
_transfer(msg.sender,to,value);
return true;
}
function transferFrom(address from,address to,uint value)external returns(bool){
if(allowancefrom!=uint(-1)){
allowancefrom=allowancefrom.sub(value);
}
_transfer(from,to,value);
return true;
}
function permit(address owner,address spender,uint value,uint deadline,uint8 v,bytes32 r,bytes32 s)external{
require(deadline>=block.timestamp,'UniswapV2:EXPIRED');
bytes32 digest=keccak256(
abi.encodePacked(
'x19x01',
DOMAIN_SEPARATOR,
keccak256(abi.encode(PERMIT_TYPEHASH,owner,spender,value,nonces[owner]++,deadline))
)
);
address recoveredAddress=ecrecover(digest,v,r,s);
require(recoveredAddress!=address(0)&&recoveredAddress==owner,'UniswapV2:INVALID_SIGNATURE');
_approve(owner,spender,value);
}
}
首先为unit类型加上SafeMath的方法
using SafeMath for uint;
然后定义一些所需要变量以及常量
//token的名字
string public constant name='Uniswap V2';
//token的symbol
string public constant symbol='UNI-V2';
//token所支持的精度
uint8 public constant decimals=18;
//token的总供应量
uint public totalSupply;
//地址与余额之间的映射
mapping(address=>uint)public balanceOf;
//授权交易与授权交易数额之间的映射
mapping(address=>mapping(address=>uint))public allowance;
//EIP712所规定的DOMAIN_SEPARATOR值,会在构造函数中进行赋值
bytes32 public DOMAIN_SEPARATOR;
//EIP712所规定的TYPEHASH,这里直接硬编码的keccak256("Permit(address owner,address spender,uint256 value,uint256 nonce,uint256 deadline)")所得到的值
bytes32 public constant PERMIT_TYPEHASH=0x6e71edae12b1b97f4d1f60370fef10105fa2faae0126114a169c64845d6126c9;
//地址与nonce之间的映射
mapping(address=>uint)public nonces;
定义event
//授权event
event Approval(address indexed owner,address indexed spender,uint value);
//交易event
event Transfer(address indexed from,address indexed to,uint value);
构造函数
constructor()public{
//当前运行的链的标识
uint chainId;
assembly{
//内联汇编,获取链的标识
chainId:=chainid
}
//获取DOMAIN_SEPARATOR
DOMAIN_SEPARATOR=keccak256(
abi.encode(
keccak256('EIP712Domain(string name,string version,uint256 chainId,address verifyingContract)'),
keccak256(bytes(name)),
keccak256(bytes('1')),
chainId,
address(this)
)
);
}
铸币方法这个方法主要的目的是向某个地址发送一定数量的token。
function _mint(address to,uint value)internal{
totalSupply=totalSupply.add(value);
balanceOf[to]=balanceOf[to].add(value);
emit Transfer(address(0),to,value);
}
销毁方法这个方法主要的目的是销毁某个地址的所持有的token。
function _burn(address from,uint value)internal{
balanceOf[from]=balanceOf[from].sub(value);
totalSupply=totalSupply.sub(value);
emit Transfer(from,address(0),value);
}
授权私有方法这个方法的逻辑也非常简单,就是修改allowance对应的映射并发出event
function _approve(address owner,address spender,uint value)private{
allowanceowner=value;
emit Approval(owner,spender,value);
}
approve授权方法直接调用的授权的私有方法,并返回true
function approve(address spender,uint value)external returns(bool){
_approve(msg.sender,spender,value);
return true;
}
permit授权方法该方法的参数具体含义可以查询EIP2612中的定义。
function permit(address owner,address spender,uint value,uint deadline,uint8 v,bytes32 r,bytes32 s)external{
//检查时效时间是否超时
require(deadline>=block.timestamp,'UniswapV2:EXPIRED');
//构建电子签
bytes32 digest=keccak256(
abi.encodePacked(
'x19x01',
DOMAIN_SEPARATOR,
keccak256(abi.encode(PERMIT_TYPEHASH,owner,spender,value,nonces[owner]++,deadline))
)
);
//验证签名并获取签名信息的地址
address recoveredAddress=ecrecover(digest,v,r,s);
//确保地址不是0地址并且等于token的owner
require(recoveredAddress!=address(0)&&recoveredAddress==owner,'UniswapV2:INVALID_SIGNATURE');
//进行授权
_approve(owner,spender,value);
}
转账私有方法该方法实现了一个转账的逻辑,具体逻辑也非常简单,就是将from对应的banlanceOf减去value,to对应的balanceOf加上value,最后发出Transferevent
function _transfer(address from,address to,uint value)private{
balanceOf[from]=balanceOf[from].sub(value);
balanceOf[to]=balanceOf[to].add(value);
emit Transfer(from,to,value);
}
转账方法token的拥有这直接调用的方法,将token从拥有者身上转到to地址上去
function transfer(address to,uint value)external returns(bool){
_transfer(msg.sender,to,value);
return true;
}
授权转账方法在执行该方法之前,需要通过approve授权方法或者permit授权方法进行授权。转账之前需要确认msg.sender在allowance中是否有值,如果有值就减去对应的金额。
function transferFrom(address from,address to,uint value)external returns(bool){
if(allowancefrom!=uint(-1)){
//减去对应的授权额度
allowancefrom=allowancefrom.sub(value);
}
_transfer(from,to,value);
return true;