solidity智能合约编程基础

solidity基础:

基础语法(一)

1)函数定义:
function 函数名(参数类型 参数1, 参数类型 参数2) [访问权限] [读取数据类型函数] returns (返回数据类型){}

访问权限:public 、private (一般private权限的话,参数命名前面加一个_ ,例如:_name)
读取数据类型函数:view函数(只读且不可修改);pure函数(不访问应用里的数据)

2)定义结构体并实例化:

struct  Zombie{
    string name;
    uint age;    
}
//建立struct动态数组zombies
Zombie[] zombies;
//实例化
temp = Zombie("jack", 10);
//添加数据进数组
zombies.push(temp);
//一行代码实现添加数据
zombies.push(Zombie("jack", 10));

//结构体作为参数传入:
function _doStuff(Zombie storage _zombie) internal {
}

3)强制类型转换:

uint8 a = 5;
uint b =3;
//强制转换;高位不可直接转低位,需要强制转换
uint8 c = a * uint8(b);

4)事件监听

//创建事件
event work(uint x, uint y, uint result);

function add(uint _x, uint _y) public {
     uint result = _x + _y;
     //触发事件,做出反应
     work(_x, _y, result);
     return result;
}

基础语法(二)

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

mapping(keyType => valueType) [访问权限] 映射名;
例如:
mapping(uint => address) public zombieToOwner ;
mapping(address => uint) ownerZombieCount;

2)全局变量调用函数:
Msg.sender :当前调用者(或智能合约)的address
例如:

mapping (uint => address) public zombieToOwner;
mapping (address => uint) ownerZombieCount;
uint id = zombies.push(Zombie(_name, _dna)) - 1;//id为例子
//更新zombieToOwner值
zombieToOwner[id] = msg.sender;
//为这个 msg.sender 名下的 ownerZombieCount 加 1
ownerZombieCount[msg.sender]++;

3)Require:函数在执行过程中,当不满足某些条件时抛出错误,并停止执行

// 两字符串的 keccak256 哈希值来进行判断)
require(keccak256(_name) == keccak256("Vitalik"));

4)继承:
 例如:ZombieFeeding 继承自 ZombieFactory 合约

contract ZombieFeeding is ZombieFactory {

}

5)引入(import):
例如:将 zombiefactory.sol 导入到我们的新文件 zombiefeeding.sol 中

import "./zombiefactory.sol ";

6)storage和memory:
Storage 变量是指永久存储在区块链中的变量。 Memory 变量则是临时的,当外部函数对某合约调用完成时,内存型变量即被移除。
Solidity默认处理:状态变量(在函数之外声明的变量)默认为“存储”形式,并永久写入区块链;而在函数内部声明的变量是“内存”型的,它们函数调用结束后消失。
例如:

//创建一个storage变量 (Zombie为struct类型)
Zombie storage storage; 

7)internal和external修饰符:
internal:如果某个合约继承自其父合约,这个合约即可以访问父合约中定义的“内部”函数。
external:函数只能在合约之外调用,它们不能被合约内的其他函数调用。

8)合约接口:
例如:创建KittyInterface 接口

contract KittyInterface {
     function getKitty(uint256 _id) external view return(bool isGestating,);
}

使用接口:创建一个名为 kittyContract 的 KittyInterface,并用 ckAddress 为它初始化

KittyContract kittyContract = KittyContract(ckAddress);

9)处理返回多个值:
例如:multipleReturns()函数可以返回3个值

(a, b, c) = multipleReturns();
若只返回c:
( ,  , c) = multipleReturns();

基础语法(三)

1)智能协议永固性:
代码不可更改和更新

2)onlyOwner函数修饰符;
为了确保函数值能被合约拥有者调用,添加onlyOwner函数修饰符确保
(调用权限限制)
例如:
function likeABoss() external onlyOwner {
}

3)gas:
gas:驱动以太坊DApps的能源(可以通过结构封装节约gas;将相同类型变量放在一起或者尽可能使用最小的整数子类型)

4)时间单位:
变量now可以返回当前的时间戳

5)公有函数和安全性:
检查声明为public和external的函数,若没有onlyOwner,可以在能够使用internal避免安全问题。

6)利用view节约gas:
在所能只读的函数上标记上表示“只读”的“external view 声明,就能为你的玩家减少在 DApp 中 gas 用量。

基础语法(四)

1)可支付函数修饰符:payable
总结:
private 意味着它只能被合约内部调用; internal 就像 private 但是也能被继承的合约调用; external 只能从合约外部调用;最后 public 可以在任何地方调用,不管是内部还是外部。
view 告诉我们运行这个函数不会更改和保存任何数据; pure 告诉我们这个函数不但不会往区块链写数据,它甚至不从区块链读取数据。这两种在被从合约外部调用的时候都不花费任何gas(但是它们在被内部其他函数调用的时候将会耗费gas)。
onlyOwner 和 aboveLevel。 对于这些修饰符我们可以自定义其对函数的约束逻辑。
payable 方法是一种可以接收以太的特殊函数。

例如:

contract OnlineStore {
  function buySomething() external payable {
    // 检查以确定0.001以太发送出去来运行函数:
    require(msg.value == 0.001 ether);
    // 如果为真,一些用来向函数调用者发送数字内容的逻辑
    transferThing(msg.sender);
  }
}

msg.value 是一种可以查看向合约发送了多少以太的方法。

2)提现:

contract GetPaid is Ownable {
  function withdraw() external onlyOwner {
    owner.transfer(this.balance);
  }
}

transfer 函数向一个地址发送以太, 然后 this.balance 将返回当前合约存储了多少以太。

3)随机数(不安全的方式):

uint random = uint(keccak256(now, msg.sender, randNonce));

基础语法(五)

1)ERC721标准和多重继承:

contract ERC721 {
  event Transfer(address indexed _from, address indexed _to, uint256 _tokenId);
  event Approval(address indexed _owner, address indexed _approved, uint256 _tokenId);

  function balanceOf(address _owner) public view returns (uint256 _balance);
  function ownerOf(uint256 _tokenId) public view returns (address _owner);
  function transfer(address _to, uint256 _tokenId) public;
  function approve(address _to, uint256 _tokenId) public;
  function takeOwnership(uint256 _tokenId) public;
}

例如:
// 对 ERC721 和ZombieAttack  的继承

contract ZombieOwnership is ZombieAttack , ZRC721{

}

balanceOf:返回代币数
ownerOf:返回代币所有者
transfer:代币交易
approve:批准交易
takeOwnership:简单地检查以确保 msg.sender 已经被批准来提取这个代币

2)预防溢出
溢出:假设我们有一个 uint8, 只能存储8 bit数据。这意味着我们能存储的最大数字就是二进制 11111111 (或者说十进制的 2^8 - 1 = 255)。

下溢:果你从一个等于 0 的 uint8 减去 1, 它将变成 255 (因为 uint 是无符号的,其不能等于负数)。

安全数学库:SafeMath
使用库:using SafeMath for uint256 
SafeMath 库有四个方法:add, sub, mul, 以及 div。
调用: 
uint256 =a; 
a.add(1);

防止 uint16 和 uint32 溢出或下溢。我们可以将其命名为 SafeMath16 和 SafeMath32。

 

参考资料:https://cryptozombies.io/zh/course/

  • 0
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 1
    评论
Solidity是一种智能合约语言,它是以太坊平台上的主要编程语言之一。以下是Solidity的教程: 1. 智能合约基础结构 Solidity智能合约由两个部分组成:状态变量和函数。状态变量是合约内部存储的数据,而函数是合约内部的代码,用于处理状态变量或执行其他操作。 2. Solidity的数据类型 Solidity支持各种数据类型,包括布尔值、整型、地址、字符串、数组、结构体等。例如: - 布尔值:bool - 整型:int、uint - 地址:address - 字符串:string - 数组:array - 结构体:struct 3. Solidity的函数 函数是Solidity合约中最重要的部分之一。函数可以接受参数,也可以返回值。例如: ``` function add(uint a, uint b) public returns (uint) { return a + b; } ``` 这个函数接受两个整数作为参数,并返回它们的和。 4. Solidity的控制流 Solidity支持各种控制流结构,包括if、for、while、do-while等。例如: ``` function isEven(uint x) public returns (bool) { if (x % 2 == 0) { return true; } else { return false; } } ``` 这个函数接受一个整数作为参数,并返回它是否为偶数。 5. Solidity的事件 事件是Solidity合约中的一种通知机制,它可以向外部应用程序发送消息。例如: ``` event Transfer(address indexed _from, address indexed _to, uint _value); ``` 这个事件表示在合约中发生了一次转账操作,它包含了发送方地址、接收方地址和转账金额。 6. Solidity继承 Solidity支持继承,一个合约可以从另一个合约中继承状态变量和函数。例如: ``` contract A { uint public x = 1; } contract B is A { uint public y = 2; } ``` 在这个例子中,合约B从合约A中继承了状态变量x,并且定义了自己的状态变量y。 以上就是Solidity基础教程,希望对你有所帮助。

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值