【Solidity学练系列2---僵尸攻击人类】

本文深入探讨了Solidity编程语言,通过创建一个僵尸游戏合约,讲解了映射、地址、msg.sender、require、继承、接口等概念。在合约中,创建了zombieToOwner和ownerZombieCount映射,确保每个用户只能创建一个僵尸。同时介绍了如何限制功能的调用,防止恶意行为。此外,还展示了如何通过接口与CryptoKitties合约交互,实现僵尸捕猎和繁殖功能。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

备注

  • 本章是 【Solidity学练系列1—搭建僵尸工厂】 的进阶版,强烈建议从系列1开始看;
  • 还是那句话,实实在在的抄一遍,比囫囵吞枣的看一遍的效果好的多得多得多!
  • 文章排版还在摸索中,如果看得有点乱,实在抱歉,因为发表这文章的主要目的还是自学+分享
  • 还是强烈建议去 浅显易懂+打怪通关式学习+自带编辑器 的开源Solisity学习网站 僵尸攻击人类 学习。

1. 映射(Mapping)和地址(Address)

Address(地址)

以太坊区块链由_account_(账户)组成,你可以把它想象成银行账户。一个账户的余额是_以太_(在以太坊区块链上使用的币种),你可以和其他账户之间支付和接受以太币,就像你的银行账户可以电汇资金到其他银行账户一样。
每个帐户都有一个“地址”,你可以把它想象成银行账号。这是账户唯一的标识符,它看起来长这样:0x0cE446255506E92DF41614C46F1d6df9Cc969183

Mapping(映射)

映射 是另一种在Solidity中存储有组织数据的方法;
映射是这样定义的:

//对于金融应用程序,将用户的余额保存在一个uint类型的变量中;
mapping(address => uint) public accountBalance;
// 或者可以用来通过userId存储/查找的用户名
mapping(uint => string) userIdToName;

映射本质上是存储和查找数据所用的键-值对。 类似java的Map。

2. Msg.sender

在solidity中,有一些全局变量可以被所有函数调用。其中一个就是msg.sender,它指的是当前调用者(或智能合约)的address。

注:在Solidity中,功能执行始终需要从外部调用者开始,一个合约只会在区块链上什么也不做,除非有人调用其中的函数,所以msg.sender总是存在的。
以下是使用msg.sender来更新mapping的例子:

mapping(address => uint) favoriteNumber;

function setMyNumber(uint _myNumber) public {
	// 更新我们的 `favoriteNumber` 映射来将 `_myNumber`存储在 `msg.sender`名下
	favoriteNumber[msg.sender] = _myNumber;
	 // 存储数据至映射的方法和将数据存储在数组相似
}

function whatIsMyNumber() public view returns (uint) {
	  // 拿到存储在调用者地址名下的值
	  // 若调用者还没调用 setMyNumber, 则值为 `0`
	return favoriteNumber[msg.sender];
}

在这个小小的例子中,任何人都可以调用 setMyNumber 在我们的合约中存下一个 uint 并且与他们的地址相绑定。 然后,他们调用 whatIsMyNumber 就会返回他们存储的 uint。

使用msg.sender很安全,因为它具有以太坊区块链的安全保障—除非窃取与以太坊地址相关联的私钥,否则是没有办法修改其他人的数据的;

3. Require

require 使得函数在执行过程中,当不满足某些条件时抛出错误,并停止执行;

function sayHiToVitalk(string _name) public returns(string) {
  	// 比较 _name 是否等于 "Vitalik". 如果不成立,抛出异常并终止程序
  	// (敲黑板: Solidity 并不支持原生的字符串比较, 我们只能通过比较
  	// 两字符串的 keccak256 哈希值来进行判断)
  	require(keccak256(_name) == keccak256("Vitalik"));
	// 如果返回 true, 运行如下语句
  	return "Hi!";
}

如果你这样调用函数 sayHiToVitalik(“Vitalik”) ,它会返回“Hi!”。而如果调用的时候使用了其他参数,它则会抛出错误并停止执行。
因此,在调用一个函数之前,用require验证前置条件是非常有必要的;

4. 继承(Inheritance)

当代码过于冗长的时候,最好将代码和逻辑分拆到多个不同的合约中,以便于管理;有个让Solidity的代码易于管理的功能,就是合约inheritance(继承)。

contract Doge {
	function catchphrase() public returns(string) {
		return "So Wow CryptoDoge";
	}
}

contract BabyDoge is Doge {
	function anotherCatchphrase() public returns(string) {
		return "Such Moon BabyDoge";
	}
}

由于BabyDoge是从Doge那里inherits(继承)过来的;这意味着当你编译和部署了BabyDoge,它就可以访问catchphrase()和anotherCatchphrase()和其他我们在 Doge中定义的其他公共函数 。这可以用于逻辑继承,(比如表达子类的时候,Cat是一种Anamal)。但也可以简单地将类似的逻辑组合到不同的合约中以组织代码;

5. 引入(Import)

在Solidity中,当你有多个文件并且想把一个文件导入到另一个文件时,可以使用import语句;

import "./someothercontract.sol";

contract newContract is
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值