solidity基础语法与简单案例20221202

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);
    }

}

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值