solidity(智能合约)零基础教学(5)

下面给大家分享一些solidity的一些必备知识点

一,智能合约转账时可以用到功能:receive和fallback。两者都接收以太币由于它们主要用于处理外部消息和事件,因此它们都不能直接从内部函数调用所以需要external来修饰。

(1)receive函数只在接收到以太币时运行。当我们向Funder合约发送以太币时,receive函数将被执行。

receive() external payable { }

(2)fallback函数在接收到任何类型的消息时都会执行。即使不是以太币,只要您向Funder合约发送任何类型的消息,fallback函数就会被执行。

fallback() external payable { }

二,调用加密算法,将字符装换成为32为的哈希值

  function generateRandom(string memory _str)public pure returns(bytes32){
        return keccak256(abi.encodePacked(_str));
    } 

最后我们来写第一个合约

// SPDX-License-Identifier: MIT
pragma solidity ^0.8.2;

contract mulutiSigWallet{
    // 事件一:往多钱包里面存钱
    event Deposit(address indexed sender, uint amout);
    // 事件二:提交交易txID = transaction ID 交易的序号
    event Submit(uint indexed txID);
    // 事件三:当有人提交交易时,允许交易
    event Approve(address indexed owner, uint indexed txID);
    // 事件四,撤销交易
    event Revoke(address indexed owner, uint txID);
    // 事件五:执行交易
    event Excute(uint indexed txID);

    // 建立一个修饰符,检测该方法的地址是否是钱包所有人之一
    modifier OnlyOwner(){
        require(isOwner[msg.sender], "you are not one of the owner");
        _;
    }
    // 输入的交易序列号不能超过交易的总数
    modifier txExists(uint _txID){
        require(_txID < transactions.length);
        _;
    }

    // 建立一个函数修饰符 ,用于检查该交易是否已经被调用该函数同意了
    modifier notApproved(uint _txID){
        require(!approved[_txID][msg.sender], "you have already approved this transacthion");
        _;
    }

    // 建立一个函数修饰符,用于检查该笔交易是否已经执行了
    modifier notExecuted(uint _txID){
        require(!transactions[_txID].executed, "this tx has already excuted");
        _;
    }

    // 定义一个交易的结构体
    struct Transaction{
        address to;
        uint value;
        bytes data;
        bool executed;//交易是否执行
    }
    // 往该多签钱包存钱用户的地址
    address sender ;
    // 多签钱包的所以着的列
    address[] public owners;
    // 定义一个mapping方法,判断这个地址是不是多签钱包所有者
    mapping(address => bool) public isOwner;
    // 定义一个数,这个变量代表需要多少人以上完成一笔交易
    uint public required;
    // 定义一个所有元素类型为Transaction的列表,
    Transaction[]  public transactions;
    // 建立一个多重mapping方法,交易的序号->address->bool
    mapping(uint => mapping(address => bool)) public approved;
    // 创建一个构造函数,输入一个所有者地址和最小需要多少人同意才能执行一笔交易
    constructor(address[] memory _owner, uint _required){
        // 加一个修饰符,限制owner必须有地址
        require(_owner.length > 0, "owners can not be zero");
        // 加一个修饰符,限制最小同意的人数,必须大于0且小于钱包的所以者数量
        require(_required > 0 && _required < _owner.length, "invalid required numbers");
        // 检查每个地址有没有重复读取
        for(uint i; i <= _owner.length; i++){
            address owner = owners[i];
            // 建立一个修饰符,保证每个输入的地址不为0x0000...00
            require(owner != address(0), "0x0000...00 not vaild owners!");
            // 保证没有重复的值
            require(!isOwner[owner], "the address is already be the owner");
            // 读取过的地址标记一下
            isOwner[owner] = true;
            // 往owner里面插入owner这个地址
            owners.push(owner);
            // required人数就是我们输入的_reqired
            required = _required;

        }
    }
    // 建立一个receive功能,让我们的合约可以收款,每当有地址往里面转以太坊的时候,就排除一个Deposit事件
    receive() external payable {
        emit Deposit(msg.sender, msg.value);
    }
    // 建立一个function:submitu用于提交一笔交易
    function submit(address _to, uint _value, bytes calldata _data) external payable OnlyOwner{
        transactions.push(Transaction({
            to:_to,
            value:_value,
            data:_data,
            executed:false
        }));
        emit Submit(transactions.length - 1);
    }
    // 用于同意某笔交易
    function approve(uint _txID)
        external 
        OnlyOwner
        txExists(_txID)
        notApproved(_txID)
        notExecuted(_txID)
    {
        approved[_txID][msg.sender] = true;
        emit Approve(msg.sender, _txID);
    }

    // 统计有多少人
    function _getthenumberconfirm(uint _txID) public view returns (uint count){
        for(uint i = 0; i < owners.length; i++){
            if(approved[_txID][owners[i]]){
                count++;
            }
        }
    }

    function executedTransaction(uint _txID)
        public
        OnlyOwner
        txExists(_txID)
        notExecuted(_txID)
        {
            // 这里再复习一下storage需要修改链上的数据的封装类型,
            // memory用于,我只拿去链上的数据,不做修改
            Transaction storage transaction = transactions[_txID];

            require(_getthenumberconfirm(_txID) > required, "not enough people agree this transaction");
            transaction.executed = true;

            // 转账
            (bool success,) = payable (transaction.to).call{value:transaction.value}(
                transaction.data
            );
            require(success, "tx failed");
            // 上面也可以用下面这个代替转账
            // payable(transaction.to).transfer(transaction.value);
            
            emit Excute(_txID);
        }

        // 用于撤销已提交的事务
        function revokeTransaction(uint _txID) public OnlyOwner txExists(_txID) notExecuted(_txID){
            require(approved[_txID][msg.sender] == true, "not approved!");
            approved[_txID][msg.sender] = false;
            emit Revoke(msg.sender, _txID);
        }
}

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值