solidity实现智能合约教程(3)-空投合约

这篇具有很好参考价值的文章主要介绍了solidity实现智能合约教程(3)-空投合约。希望对大家有所帮助。如果存在错误或未考虑完全的地方,请大家不吝赐教,您也可以点击"举报违法"按钮提交疑问。

猛戳订阅学习专栏🍁🍁 👉 solidity系列合约源码+解析 👈 🍁🍁

solidity实现智能合约教程(3)-空投合约

1 介绍

空投就是一种营销策略,通过空投活动将某种数字货币或代币分发给用户,通常需要用户完成一项简单的任务,如分享新闻、介绍朋友或拥有某种数字货币,目前也被广泛应用于宣传新币种,在数字货币市场中反响不错。本文将和大家一起编写我们常见的糖果空投合约。

“发送 0 个 ETH 到某个地址,立马获得 5000 枚 Token,每个地址只能获取一次”,相信大家对于此类糖果空投的信息都已经遇见过很多次了,也有很多朋友趁此机会薅了很多羊毛。身为开发人员,我们不应只是简单的薅羊毛,更应该深入地去研究此类糖果空投的实现原理。

最简单的实现方式是通过人工手动来处理每笔空投,但耗时耗力不够智能还极易出错。若是通过智能合约来实现,不仅省时省力,还不易出错。

2 主要功能

本篇文章空投合约实现主要功能:

  1. 通过合约给单个地址转ETH
  2. 通过合约一次性给多个地址转ETH(平均分配金额)
  3. 通过合约一次性给多个地址转ETH(指定金额)
  4. 通过合约一次性给多个地址转移ERC20代币(固定个数)
  5. 通过合约一次性给多个地址转移ERC20代币(指定个数)
  6. 通过合约给单个地址转移ERC721 NFT(指定NFT)
  7. 通过合约给单个地址转移单个ERC1155代币
  8. 通过合约给单个地址转移不同数量的ERC1155代币

我们先来看一下标准的 ERC20 标准的接口:

3 代码示例

本篇文章使用到的智能合约开发库:
openzeppelin
有兴趣的同学可以去看一下他们的源码。

下面让我们来给出完整的空投合约代码:

合约代码:

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

import "@openzeppelin/contracts/token/ERC721/IERC721.sol";
import "@openzeppelin/contracts/token/ERC20/IERC20.sol";
import "@openzeppelin/contracts/token/ERC1155/IERC1155.sol";

contract kongTou {

 
    address owner;


    modifier onlyOwner() {
        require(msg.sender == owner, "only owner can call this");
        _;
    }

    modifier notAddress(address _useAdd){
        require(_useAdd != address(0), "address is error");
        _;
    }

    event Received(address, uint);

    constructor() payable{
        owner = msg.sender;
    }

    receive() external payable {
        emit Received(msg.sender, msg.value);
    }

    function pay() public payable{

    }

    function transferEthsAvg(address[] memory _tos) 
        payable 
        public 
        onlyOwner
        returns (bool) {

        require(_tos.length > 0);

        uint oneValue = address(this).balance/_tos.length;

        for(uint i=0; i<_tos.length; i++){
            require(_tos[i] != address(0));
            payable(_tos[i]).transfer(oneValue);
        }

        return true;

    }

    function transferEths(address[] memory _tos,uint256[] memory _values) 
        payable 
        public 
        onlyOwner
        returns (bool) {

        require(_tos.length > 0);
        require(_tos.length == _values.length);

        for(uint32 i=0;i<_tos.length;i++){
            require(_tos[i] != address(0));
            require(_values[i] > 0);
            payable(_tos[i]).transfer(_values[i]);
        }

        return true;
    }

    function transferEth(address _to) 
        payable 
        public 
        onlyOwner
        returns (bool){

        require(_to != address(0));
        require(msg.value > 0);

        payable(_to).transfer(msg.value);

        return true;

    }

    function checkBalance() 
        public 
        view 
        returns (uint) {

        return address(this).balance;
    }



    function destroy() 
        public
        onlyOwner
         {

        selfdestruct(payable(msg.sender));

    }

    function transferTokensAvg(address from,address _constractAdd,address[] memory _tos,uint _v)
        public 
        onlyOwner
        notAddress(from)
        notAddress(_constractAdd)
        returns (bool){

        require(_tos.length > 0);
        require(_v > 0);

        IERC20 _token = IERC20(_constractAdd);
        

        //要调用的方法id进行编码
        // bytes4 methodId = bytes4(keccak256("transferFrom(address,address,uint256)"));

        for(uint i=0;i<_tos.length;i++){
            require(_tos[i] != address(0));

            require(_token.transferFrom(from,_tos[i],_v));
            // _constractAdd.call(abi.encodeWithSignature("transferFrom(address,address,uint256)",from,_tos[i],_v));
            // _constractAdd.call(methodId,from,_tos[i],_v);
        }
        return true;

    }


    function transferTokens(address from,address _constractAdd, address[] memory _tos,uint[] memory _values)
        public 
        onlyOwner
        notAddress(from)
        returns (bool){

        require(_tos.length > 0);
        require(_values.length > 0);
        require(_values.length == _tos.length);

        bool status;
        bytes memory msgs;

        //要调用的方法id进行编码
        // bytes4 methodId = bytes4(keccak256("transferFrom(address,address,uint256)"));

        for(uint i=0;i<_tos.length;i++){
            require(_tos[i] != address(0));
            require(_values[i] > 0);


            (status,msgs) = _constractAdd.call(abi.encodeWithSignature("transferFrom(address,address,uint256)",from,_tos[i],_values[i]));
            require(status == true);

            // require(_constractAdd.call(methodId,from,_tos[i],_values[i]));
            
        }

        return true;

    }

    function transferTokenOne(address _from,address _constractAdd,address _to,uint _tokenId)
        public
        notAddress(_from)
        notAddress(_constractAdd)
        notAddress(_to)
        onlyOwner
        returns(bool){
            IERC721 _token = IERC721(_constractAdd);
            _token.safeTransferFrom(_from,_to,_tokenId);
            return true;
        }

    function transferToken1155(address _from,address _contractAdd,address _to,uint _tokenId,uint _num)
        public
        notAddress(_from)
        notAddress(_contractAdd)
        notAddress(_to)
        returns(bool){
            IERC1155 _token = IERC1155(_contractAdd);
            _token.safeTransferFrom(_from,_to,_tokenId,_num,"");
            return true;
        }

    function transferTokenBatch1155(address _from,address _contractAdd,address _to,uint[] memory _tokenIds,uint[] memory _nums)
        public
        notAddress(_from)
        notAddress(_contractAdd)
        notAddress(_to)
        returns(bool){
            IERC1155 _token = IERC1155(_contractAdd);
            _token.safeBatchTransferFrom(_from,_to,_tokenIds,_nums,"");
            return true;
        }

}

下面解释一下上面用到的合约和方法:

  • @openzeppelin/contracts/token/ERC721/IERC721.sol 该合约实现了标准的IERC721接口中的方法
  • @openzeppelin/contracts/token/ERC20/IERC20.sol 该合约实现了标准的IERC20接口中的方法
  • @openzeppelin/contracts/token/ERC1155/IERC1155.sol 该合约实现了标准的IERC1155接口中的方法
  • modifier onlyOwner() 该修饰器为修饰某个方法权限为只能合约部署者调用
  • modifier notAddress(address _useAdd) 改修饰器为修饰判断某个address类型的值不为0地址
  • event Received() 该event事件为合约收到转账时候触发
  • constructor() //合约的构造方法,在合约创建时候存储合约创建者的地址,添加payable,支持在创建合约的时候,value往合约里面转eth
  • receive() 当合约收到转账时候该方法会被调用,方法内实现了去触发Received event事件
  • pay() 该方法定义了payable,代表后面可以通过该方法往合约里面转移ETH
  • transferEthsAvg(address[] memory _tos) //批量转移ETH,平分发给_tos数组里面的地址,
  • transferEths(address[] memory _tos,uint256[] memory _values) //给每个地址转不同数量的ETH,其中_tos和_values数组里面的地址和数量要一一对应
  • transferEth(address _to) //通过合约直接给_to地址转移ETH
  • checkBalance() //检查合约账户剩余的可用ETH数量
  • destroy() 销毁合约,合约被销毁后,合约中剩余的ETH将会被转移到合约铸造者地址中,且合约后面将不再可用
  • transferTokensAvg(address from,address _constractAdd,address[] memory _tos,uint _v) //批量给每一个地址转移ERC20 Token,每个地址转一样数量, 其中 from为要转出token的地址,_constractAdd为要转移的ERC20的合约地址,_tos为要批量转给的用户数组,_v为给每个地址转移的ERC20的数量
  • transferTokens(address from,address _constractAdd, address[] memory _tos,uint[] memory _values) //批量给每一个地址转移ERC20 Token,每个地址转不一样的数量,其中 from为要转出token的地址,_constractAdd为要转移的ERC20的合约地址,_tos为要批量转给的用户数组,_values为给每个地址转移的ERC20的数量,_tos和_values要一一对应
  • transferTokenOne(address _from,address _constractAdd,address _to,uint _tokenId) //转移单个ERC721的NFT,其中 from为要转出token的地址,_constractAdd为要转移的ERC721的合约地址,_to为要转到的地址,_tokenId为要转移的ERC721的token ID
  • transferToken1155(address _from,address _contractAdd,address _to,uint _tokenId,uint _num) //转移单个ERC1155的代币,其中 from为要转出token的地址,_constractAdd为要转移的ERC1155的合约地址,_to为要转到的地址,_tokenId为要转移的ERC721的token ID,_num为要转移的该token ID的数量
  • transferTokenBatch1155(address _from,address _contractAdd,address _to,uint[] memory _tokenIds,uint[] memory _nums) //给某个address转移多个ERC1155的代币,其中 from为要转出token的地址,_constractAdd为要转移的ERC1155的合约地址,_to为要转到的地址,_tokenIds为要转移的ERC721的token ID组成的数组,_nums为要转移的token ID的数量组成的数组

注意:在操作转移相应的token之前,都要先用相应的_from地址调用token合约的授权方法,允许该空投合约转移_from地址一定数量的token

4 部署测试

solidity实现智能合约教程(3)-空投合约

我们选择要部署的合约为 kongtou ,点击 Deploy 进行部署,可以看到部署后的合约地址和相应的合约方法

solidity实现智能合约教程(3)-空投合约

为了测试我们的空投合约的功能,再部署一下前面学到的ERC20合约,部署时候要换一个地址,并给该地址铸造了1000个代币。

solidity实现智能合约教程(3)-空投合约
下面给空投合约授权转移的token数量为100个,为了下一步的批量转移token。并且查询验证一下。

solidity实现智能合约教程(3)-空投合约
接下来我们给2个地址转移了ERC20 token,每个地址转移的数量为25个,这一步调用合约时候的地址为 部署空投合约的地址

solidity实现智能合约教程(3)-空投合约
最后一步我们用之前接收ERC20代币的地址数组中的一个查询一下他的ERC20的余额,结果为25个,验证了我们的此次批量转移token是成功的。

好了,批量转移token的空投合约到这里就结束了,学会了这个合约就可以举一反三做出来很多其他类似的空投合约!文章来源地址https://www.toymoban.com/news/detail-466382.html

到了这里,关于solidity实现智能合约教程(3)-空投合约的文章就介绍完了。如果您还想了解更多内容,请在右上角搜索TOY模板网以前的文章或继续浏览下面的相关文章,希望大家以后多多支持TOY模板网!

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处: 如若内容造成侵权/违法违规/事实不符,请点击违法举报进行投诉反馈,一经查实,立即删除!

领支付宝红包 赞助服务器费用

相关文章

  • Solidity智能合约开发 — 3.4-抽象智能合约和接口

    假如一个智能合约中至少一个函数缺省实现时,即某个函数缺少{}中的内容,这个智能合约就当做抽象智能合约。 当我们有一个函数没想好怎么写时,必须将该合约标为 abstract ,不然编译会报错;另外,未实现的函数需要加 virtual ,以便子合约重写。抽象智能合约是将智能合

    2024年02月12日
    浏览(35)
  • 【Solidity】智能合约案例——①食品溯源合约

    目录 一、合约源码分析: 二、合约整体流程:       1.部署合约       2.管理角色       3.食品信息管理       4.食品溯源管理         Producer.sol:生产者角色的管理合约,功能为:添加新的生产者地址、移除生产者地址、判断角色地址是否被授权         Di

    2024年02月08日
    浏览(38)
  • 以太坊智能合约开发(五):Solidity成绩录入智能合约实验

    每个学生分别部署合约Student.sol ,保证只有自己可以修改姓名。老师部署合约StudentScore.sol,用于录入学生成绩,查询学生信息。查询学生信息时,需要调用学生部署的合约Student.sol。 student.sol合约,用于学生对自己信息进行管理。 学生的基本信息作为状态变量: 声明构造函

    2024年02月07日
    浏览(36)
  • 【区块链技术开发】 Solidity使用Truffle Box工具实现预构建模板、自动化部署、创建智能合约示例代码

    专栏:区块链技术开发 Truffle Box是一个开发工具,为Truffle生态系统中的开发人员提供了预构建

    2023年04月16日
    浏览(41)
  • 【Solidity】智能合约案例——③版权保护合约

    目录 一、合约源码分析: 二、合约整体流程:         1.部署合约:         2.添加实体:          3.查询实体         4.审核版权:         5.版权转让         Copyright.sol:主合约,定义了版权局的实体,功能为:审核版权         Opus.sol:定义两个实体:作者和作

    2024年02月04日
    浏览(35)
  • Solidity 智能合约入门

    将一个数据放置在链上 我们对代码进行逐行分析,首先第一行 第一行表明此段代码是被GPL-3.0所授权。默认情况下,在发布源代码时加入机器可读许可证说明是很重要的。 GPL(GNU General Public License Versions) GPL协议一般还可以分为GPL2.0和GPL3.0两种,而GPL3.0是更新一代的开源标准

    2024年02月02日
    浏览(36)
  • solidity开发智能合约

    起源于以太坊(Ethereum),设计的目的是能在以太坊虚拟机(EVM)上运行。Solidity 是一门面向合约的、为实现智能合约而创建的高级编程语言。所以先从智能合约开始。 参考文档 Solidity文档:区块链技术-智能合约Solidity编程语言 solidity官方文档: https://solidity-cn.readthedocs.io/

    2023年04月08日
    浏览(72)
  • 智能合约 Solidity – 构造函数

    构造函数是任何面向对象的编程语言中的一种特殊方法,每当初始化类的对象时都会调用它。Solidity 则完全不同,Solidity 在智能合约内部提供了一个构造函数声明,它只在合约部署时调用一次,用于初始化合约状态。如果没有明确定义的构造函数,则编译器会创建默认构造函

    2024年02月11日
    浏览(34)
  • solidity:智能合约结构介绍

    合约结构介绍 1.SPDX 版权声明 bytecode metadata 介绍 2.pragma solidity 版本限制 3.contract 4.import 导入声明 5.interface: 接口 6.library:库合约 第 1 行 // SPDX-License-Identifier: MIT 就是合约的版权声明。其中 SPDX-License-Identifier (SPDX 许可标示) 是标注当前的智能合约采用什么样的对外开放标

    2023年04月08日
    浏览(34)
  • 【Solidity】智能合约案例——②供应链金融合约

    目录 一、合约源码分析: 二、合约整体流程:         1.部署合约:         2.添加实体         3.发送交易存证            ①.银行向公司交易(公司向银行提供交易存证)            ②.公司向银行交易(银行向公司提供交易存证)            ③.公司向公司交易

    2024年02月06日
    浏览(29)

觉得文章有用就打赏一下文章作者

支付宝扫一扫打赏

博客赞助

微信扫一扫打赏

请作者喝杯咖啡吧~博客赞助

支付宝扫一扫领取红包,优惠每天领

二维码1

领取红包

二维码2

领红包