1、权限控制合约
核心:
嵌套映射
功能:
具有多种角色身份时,不同身份具有不同的权限
角色=>账户=>权限
// SPDX-License-Identifier:MIT
pragma solidity ^0.8.7;
contract AccessControl{
event GrantRole(bytes32 indexed role, address indexed account);
event RevokeRole(bytes32 indexed role, address indexed account);
//使用bytes代替字符串能够降低消耗的gas
mapping(bytes32 => mapping(address => bool)) public roles;
//生成主键
// 0xdf8b4c520ffe197c5343c6f5aec59570151ef9a492f2c624fd45ddde6135ec42
bytes32 public constant ADMIN = keccak256(abi.encodePacked("ADMIN"));
//0x2db9fd3d099848027c2383d0a083396f6c41510d7acfd92adc99b6cffcf31e96
bytes32 public constant USER = keccak256(abi.encodePacked("USER"));
constructor(){
_grantrole(ADMIN,msg.sender);
}
modifier onlyRole(bytes32 _role){
require(roles[_role][msg.sender],"not authorized");
_;
}
function _grantrole(bytes32 _role,address _account) internal {
roles[_role][_account] = true;
emit GrantRole(_role,_account);
}
function grantRole(bytes32 _role,address _account) external onlyRole(ADMIN){
_grantrole(_role,_account);
}
function revokeRole(bytes32 _role,address _account) external onlyRole(ADMIN){
roles[_role][_account] = false;
emit RevokeRole(_role,_account);
}
}
2、自毁合约
selfdesctruct(address)
该函数能够强行发送主币
// SPDX-License-Identifier:MIT
pragma solidity ^0.8.7;
contract Kill{
constructor() payable{}
function kill() external {
selfdestruct(payable(msg.sender));
}
function testCall() external pure returns(uint){
return 123;
}
}
//测试强制发送主币、通过其他合约调用合约自毁功能,并获取主币
contract Helper{
function getBalance() external view returns(uint){
return address(this).balance;
}
function kill(Kill _kill) external {
_kill.kill();
}
}
3、IERC20
ERC20代币标准:不是一套代码,而是一套具有目标功能的接口。
功能包括:
铸造代币、销毁代币
发行代币总额查询、记录并查询某地址代币余额;
向某地址发送一定数量代币;
A地址向B地址批准一定数量的代币、用户调用合约,从A地址向B地址发放一定数量的代币
// SPDX-License-Identifier:MIT
pragma solidity ^0.8.7;
interface IERC20{
//合约发布的代币总量
function totalSupply() external view returns (uint);
//某一个账户的当前余额
function balanceOf(address account) external view returns (uint);
//把当前账户一部分余额发送至另一个账户中
function transfer(address recipient, uint amount) external returns (bool);
//查询某个账户中批准了多少金额
function allowance(address owner, address spender) external view returns (uint);
//为某一个账户批准一定数量的资金
function apporve(address spender,uint amount) external returns (bool);
//从一个账户向另一个账户转移一定量资金
function transferFrom(address spender,address recipient,uint amount) external returns (bool);
event Transfer(address indexed from,address indexed to,uint amount);
event Approval(address indexed owner, address indexed spender, uint amount);
}
//合约ERC20继承IERC20,意味着ERC20用于实现相关接口
contract ERC20 is IERC20 {
uint public override totalSupply;
mapping(address => uint) public override balanceOf;
//allowance:一个地址向另一个地址映射的数字
mapping(address => mapping(address => uint )) public override allowance;
//token name
string public name="Test";
string public symbol = "TEST";
//1*10^8代表了一个整数1
uint public decimals = 18;
//把当前账户一部分余额发送至另一个账户中
function transfer(address recipient, uint amount) external override returns (bool){
balanceOf[msg.sender] -= amount;
balanceOf[recipient] += amount;
emit Transfer(msg.sender,recipient,amount);
return true;
}
//为某一个账户批准一定数量的资金
function apporve(address spender,uint amount) external override returns (bool){
allowance[msg.sender][spender] = amount;
emit Approval(msg.sender,spender,amount);
return true;
}
//合约调用者要求从一个账户向另一个账户转移一定量资金
function transferFrom(address spender,address recipient,uint amount) external override returns (bool){
//合约调用者向代币发送者的账户中批准的余额降低
allowance[spender][msg.sender] -= amount;
//合约调用者的代币账户余额降低
balanceOf[spender] += amount;
//代币接收者的账户余额增加
balanceOf[recipient] += amount;
emit Transfer(spender,recipient,amount);
return true;
}
//铸币
function mint(uint amount) external {
balanceOf[msg.sender] += amount;
totalSupply += amount;
emit Transfer(address(0),msg.sender,amount);
}
//销毁
function burn(uint amount) external{
balanceOf[msg.sender] -= amount;
totalSupply -= amount;
emit Transfer(msg.sender,address(0),amount);
}
}
4、多签钱包
必须有多个人同意的情况下才能把钱包里的钱转出。
// SPDX-License-Identifier:MIT
pragma solidity ^0.8.7;
contract MultiSigWallet{
event Deposit(address indexed sender,uint amount); //存款
event Submit(uint indexed txID); //提交一个交易申请
event Apporve(address indexed owner,uint indexed txId); //合约签名人进行批准
event Revoke(address indexed owner,uint indexed txID); //撤销批准
event Execute(uint indexed txID); //执行批准
address[] public owners; //合约的拥有者
mapping(address => bool) public isOwner; //用于查找某用户是否是签名人
uint public required; //确认数,最少同意进行交易的人数
struct Transaction {
address to;//发送的地址
uint value;//发送的主币数量
bytes data; //如果地址为合约地址,那么还能够执行一些合约中的函数
bool executed; // 标记交易是否执行成功
}
Transaction[] public transactions;//构建一个交易数组,索引值即为ID号
mapping(uint => mapping(address => bool)) public approved; //某一个交易ID下,某一个地址是否批准了该交易
modifier onlyOwner{
require(isOwner[msg.sender],"only owner!");
_;
}
//判断交易id是否存在,由于id即索引,只要交易id小于数组长度,那么判断该交易存在
modifier txExists(uint _txId){
require(0<_txId && _txId< transactions.length,"tx does not exist");
_;
}
//判断签字者是否已经同意
modifier notApproved(uint _txId){
require(!approved[_txId][msg.sender],"tx already approved");
_;
}
//判断是否已经执行交易
modifier notExecuted(uint _txId){
require(!transactions[_txId].executed,"tx already executed");
_;
}
//建立构造函数,用于添加管理者和最小批准人数
constructor(address[] memory _owners,uint _required){
require(_owners.length >0 ,"owner required");//要求管理者数量大于0
require( _required <= _owners.length,//要求最小批准人数大于0且小于等于管理者数量
"invaled required num"
);
//判断地址是否有效:无效地址判断:1、0地址;2、重复地址
for (uint i;i <_owners.length;i++){
address owner = _owners[i];
require(owner != address(0),"invaled owner");
require(!isOwner[owner],"owner is not unique"); //如果地址已经存在过,那么判断为无效地址
isOwner[owner] = true;
owners.push(owner);
}
required=_required;
}
receive() external payable{
emit Deposit(msg.sender,msg.value);
}
//构建交易事件提交函数
function submit(address _to, uint _value, bytes calldata _data) external onlyOwner{
transactions.push(Transaction({
to: _to,
value: _value,
data: _data,
executed: false
}));
emit Submit(transactions.length - 1);//交易it为数组-1
}
//构建交易事件批准函数
function approve(uint _txId)
external
onlyOwner
txExists(_txId)
notApproved(_txId)
notExecuted(_txId)
{
approved[_txId][msg.sender] = true;
emit Apporve(msg.sender,_txId);
}
//计算事件有多少人批准了,获取事件批准数量
function _getApprocalCount(uint _txId) private view returns(uint count){
for(uint i;i<owners.length;i++){
if(approved[_txId][owners[i]]){
count += 1;
}
}
}
function execute(uint _txId) external txExists(_txId) notExecuted(_txId){
require(_getApprocalCount(_txId)>required,"approvals < required");
Transaction storage transaction = transactions[_txId];
transaction.executed = true;
(bool success,) = transaction.to.call{value:transaction.value}(
transaction.data
);
require(success,"tx failed");
emit Execute(_txId);
}
function revoke(uint _txId)
external
onlyOwner
txExists(_txId)
notExecuted(_txId)
{
require(approved[_txId][msg.sender],"tx not approved");
approved[_txId][msg.sender] = false;
emit Revoke(msg.sender,_txId);
}
}