1.实验内容
1.给WETH合约增加 depositTo(address _toAddress) 方法,使得充值时可以选择充值地址
2.增加DepositTo事件,在调用depositTo时可以记录msg.sender, toAddress 和充值金额。比如账户A充值,实际增加的是账户B的余额,同时使用DepositTo记录下该事件
3.给WETH合约增加withdrawTo(address _toAddress,uint256 wad) 方法,使得提现到时候可以选择提现地址
4.增加WithdrawTo事件,在调用withdrawTo时可以记录msg.sender, toAddress 和提现金额。比如账户A操作提现,可以提现到账户B,同时使用WithdrawTo记录该事件
2.合约基本内容
上述的实验内容是基于ERC20合约实现,以下我会先介绍该实验合约的基础方法,后面再介绍需要新增方法。
2.1 属性
平台代币的名字,标识和精确度。
string public name = "Wrapped ETH";
string public symbol = "WETH";
uint8 public decimals = 18;
2.2 事件
//授权
event Approval(address indexed src, address indexed guy, uint256 wad);
//转账
event Transfer(address indexed src, address indexed dst, uint256 wad);
//充值
event Deposit(address indexed dst, uint256 wad);
//提取
event Withdrawal(address indexed src, uint256 wad);
2.3 映射
//地址 => 余额
mapping(address => uint256) public balanceOf;
////A允许B使用多少代币
mapping(address => mapping(address => uint256)) public allowance;
2.4 回退函数
回调函数有fallback()和receive()两个函数。当消息调用合约时,合约里面没有对应的函数时,就会调用fallback函数和receive函数。当消息中有数据时调用fallback(),没有数据则调用receive()。
receive() external payable {
deposit();
}
function deposit() public payable {
balanceOf[msg.sender] += msg.value;
emit Deposit(msg.sender, msg.value);
}
2.5 主要方法
//给账户充值
function deposit() public payable {
balanceOf[msg.sender] += msg.value;
emit Deposit(msg.sender, msg.value);
}
//提现
function withdraw(uint256 wad) public {
require(balanceOf[msg.sender] >= wad);
balanceOf[msg.sender] -= wad;
msg.sender.transfer(wad);
emit Withdrawal(msg.sender, wad);
}
3.新增方法
- 该方法是可以给任意地址进行充值。
function depositTo(address _toAddress) external payable {
uint value = msg.value;
balanceOf[_toAddress] += value;
emit DepositTo(msg.sender, _toAddress, value);
}
- 在提现时,可以选择任意地址,包括提现给其他地址和自己。对
_toAddress使用payable表示该地址是可以接受代币的。
function withdrawto(address payable _toAddress, uint256 wad) external {
require(balanceOf[msg.sender] >= wad, "balanceOf[msg.sender] < wad");
balanceOf[msg.sender] -= wad;
_toAddress.transfer(wad);
emit WithdrawalTo(msg.sender, _toAddress, wad);
}
- 提现可以从
from地址向to地址转移
function withdrawFrom(address from, address payable to, uint256 value) external {
require(balanceOf[from] >= value, "balanceOf[from] < wad");
require(allowance[from][msg.sender] >= value, "allowance[from][msg.sender] < value");
allowance[from][msg.sender] -= value;
balanceOf[from] -= value;
to.transfer(value);
emit WithdrawalFrom(msg.sender, from, to, value);
}
4.源代码
// SPDX-License-Identifier: GPL-3.0-or-later
pragma solidity 0.7.6;
contract WETH9 {
string public name = "Wrapped ETH";
string public symbol = "WETH";
uint8 public decimals = 18;
event Approval(address indexed src, address indexed guy, uint256 wad);
event Transfer(address indexed src, address indexed dst, uint256 wad);
event Deposit(address indexed dst, uint256 wad);
event Withdrawal(address indexed src, uint256 wad);
event DepositTo(address indexed handlers, address indexed toAddress, uint value);
event WithdrawalTo(address indexed handlers, address indexed toAddress, uint value);
event WithdrawalFrom(address indexed handlers, address indexed from, address indexed to, uint value);
mapping(address => uint256) public balanceOf;
mapping(address => mapping(address => uint256)) public allowance;
receive() external payable {
deposit();
}
function deposit() public payable {
balanceOf[msg.sender] += msg.value;
emit Deposit(msg.sender, msg.value);
}
function depositTo(address _toAddress) external payable {
uint value = msg.value;
balanceOf[_toAddress] += value;
emit DepositTo(msg.sender, _toAddress, value);
}
function withdraw(uint256 wad) public {
require(balanceOf[msg.sender] >= wad);
balanceOf[msg.sender] -= wad;
msg.sender.transfer(wad);
emit Withdrawal(msg.sender, wad);
}
//在提现时,可以选择任意地址。
function withdrawto(address payable _toAddress, uint256 wad) external {
require(balanceOf[msg.sender] >= wad, "balanceOf[msg.sender] < wad");
balanceOf[msg.sender] -= wad;
_toAddress.transfer(wad);
emit WithdrawalTo(msg.sender, _toAddress, wad);
}
function withdrawFrom(address from, address payable to, uint256 value) external {
require(balanceOf[from] >= value, "balanceOf[from] < wad");
require(allowance[from][msg.sender] >= value, "allowance[from][msg.sender] < value");
allowance[from][msg.sender] -= value;
balanceOf[from] -= value;
to.transfer(value);
emit WithdrawalFrom(msg.sender, from, to, value);
}
function totalSupply() public view returns (uint256) {
return address(this).balance;
}
function approve(address guy, uint256 wad) public returns (bool) {
allowance[msg.sender][guy] = wad;
emit Approval(msg.sender, guy, wad);
return true;
}
function transfer(address dst, uint256 wad) public returns (bool) {
return transferFrom(msg.sender, dst, wad);
}
function transferFrom(
address src,
address dst,
uint256 wad
) public returns (bool) {
require(balanceOf[src] >= wad);
if (src != msg.sender && allowance[src][msg.sender] != uint256(-1)) {
require(allowance[src][msg.sender] >= wad);
allowance[src][msg.sender] -= wad;
}
balanceOf[src] -= wad;
balanceOf[dst] += wad;
emit Transfer(src, dst, wad);
return true;
}
}