以太坊智能合约Solidity

1,401 阅读10分钟

二. Solidity

1. Solidity简介

  1. 以太坊编写智能合约的语言,文件扩展名 .sol
  2. 强类型编程语言(变量类型有多种,例如int byte bool struct 等,类型之间转换时需要强转)
  3. 与javascript类似(但是JavaScript是弱类型的语言,一个var关键字自动识别数据类型)
  4. 一堆坑
  5. api手册 -》 Solidity中文手册

2.开发环境

  • Mist钱包 - 不好用,问题较多

  • Remix在线编程

  • Remix本地环境

image.png

3.第一个合约

  • 智能合约概览
每个合约中可包含:

- 状态变量(State Variables) : 就是成员变量,这个数据是上链的。
- 函数(Functions)
- 函数修饰符(Function Modifiers)
- 事件(Events)
- 结构类型(Structs Types)
- 枚举类型(Enum Types)
- mapping(key => value) 如: map[1] = 2
  • 便写一个 接收消息的方法
pragma solidity ^0.4.25;

contract Inbox{ 
    string public message; 
    
    function getMessage() public constant returns(string){
        return message;
    }
  
    function setMessage(string newMessage) public{
        message = newMessage;
    }
}
  • 语法解析

image.png

4.编译合约

4.1 原理

  • 使用remix,由高级语言变成机器语言

    1. solidity ---> bytecode - 机器语言,区块链系统读取
    2. solidity ---> ABI (application binary interface) - 方便程序员调用
  • 图示

image.png

4.2 bytecode

6080604052610410806100136000396000f300608060405260043610610057576000357c0100000000000000000000000000000000000000000000000000000000900463ffffffff168063368b87721461005c578063ce6d41de146100c5578063e21f37ce14610155575b600080fd5b34801561006857600080fd5b506100c3600480360381019080803590602001908201803590602001908080601f01602080910402602001604051908101604052809392919081815260200183838082843782019150505050505091929192905050506101e5565b005b3480156100d157600080fd5b506100da6101ff565b6040518080602001828103825283818151815260200191508051906020019080838360005b8381101561011a5780820151818401526020810190506100ff565b50505050905090810190601f1680156101475780820380516001836020036101000a031916815260200191505b509250505060405180910390f35b34801561016157600080fd5b5061016a6102a1565b6040518080602001828103825283818151815260200191508051906020019080838360005b838110156101aa57808201518184015260208101905061018f565b50505050905090810190601f1680156101d75780820380516001836020036101000a031916815260200191505b509250505060405180910390f35b80600090805190602001906101fb92919061033f565b5050565b606060008054600181600116156101000203166002900480601f0160208091040260200160405190810160405280929190818152602001828054600181600116156101000203166002900480156102975780601f1061026c57610100808354040283529160200191610297565b820191906000526020600020905b81548152906001019060200180831161027a57829003601f168201915b5050505050905090565b60008054600181600116156101000203166002900480601f0160208091040260200160405190810160405280929190818152602001828054600181600116156101000203166002900480156103375780601f1061030c57610100808354040283529160200191610337565b820191906000526020600020905b81548152906001019060200180831161031a57829003601f168201915b505050505081565b828054600181600116156101000203166002900490600052602060002090601f016020900481019282601f1061038057805160ff19168380011785556103ae565b828001600101855582156103ae579182015b828111156103ad578251825591602001919060010190610392565b5b5090506103bb91906103bf565b5090565b6103e191905b808211156103dd5760008160009055506001016103c5565b5090565b905600a165627a7a723058201486092ea8103d4816d5aa6177b30372d94ec850544312021159c20f3b7a505b0029

4.3 abi

  • (application binary interface,应用二进制接口)

    json格式的描述文件:

[
	{
		"constant": false,
		"inputs": [
			{
				"name": "newMessage",
				"type": "string"
			}
		],
		"name": "setMessage",
		"outputs": [],
		"payable": false,
		"stateMutability": "nonpayable",
		"type": "function"
	},
	{
		"constant": true,
		"inputs": [],
		"name": "getMessage",
		"outputs": [
			{
				"name": "",
				"type": "string"
			}
		],
		"payable": false,
		"stateMutability": "view",
		"type": "function"
	},
	{
		"constant": true,
		"inputs": [],
		"name": "message",
		"outputs": [
			{
				"name": "",
				"type": "string"
			}
		],
		"payable": false,
		"stateMutability": "view",
		"type": "function"
	},
	{
		"inputs": [],
		"payable": true,
		"stateMutability": "payable",
		"type": "constructor"
	}
]

4.4 调用

以太坊为了方便智能合约的开发、学习和测试,开启了几条全新的区块链,与主网络特性相同,但测试网络中的以太币价值更低,也更容易得到。这样不至于在主网络上开发出现 BUG 造成以太币的损失。

当然我们也可以搭建私有的测试网络,不过区块链的去中心化特点,需要更多的节点运行才能达到理想效果,好在以太坊有公开的测试网络,而我们接入也更容易。

4.4.1 运行环境
  • vm

    • account 虚拟账户5个,每个账户默认100eth。
    • 没挖矿,直接返回结果,便于开发测试
  • 网页环境

    • injected web3
    • 与metamask结合紧密
  • 自定义环境

    • web3 provider
    • 链接自己本地启动的区块链环境(truffle,ganache,私有链等)
4.4.2 部署合约
  • 部署成功后返回合约地址,如:0x27baf63ea560973e9f8f333a39239967f96c5703

  • 部署合约也是一笔交易,只不过不用填写to字段,且数据输入字段填写为合约字节码。

image.png

  • 查看浏览器

image.png

4.4.3 调用合约
  • 手动调用,我们使用手动调用,调用合约的操作分为两种类型

    • send:所有改变区块链数据状态的叫做是send操作,相当于发起一笔交易,特点是花钱,大约10s~30s(矿工确认)返回结果。

    • call:所有读取区块链合约数据的操作成为call操作,它的特点是迅速返回无需花钱

image.png

  • 通过web3调用

image.png

4.4.4 对比总结
对比项函数调用call函数调用 send transaction
数据状态不修改智能合约的数据修改智能合约的数据
返回值函数可以返回数据函数不能返回数据, 因为函数需要花时间执行
执行速度立刻执行需要十几秒才能执行完毕,返回值是transaction的hash
成本免费要花钱 钱!!!

4.5 析构函数

function destroy() {
	//析构函数,销毁当前合约,并把它所有资金发送到给定的地址
      //1.将合约里的 余额 转给 传入的地址
      //2.标记当前合约 为 销毁状态
	selfdestruct(msg.sender);
}

调用之后,合约仍然存在于区块链之上,但是函数无法被调用,调用会抛出异常。

4.6 回退函数

pragma solidity ^0.4.25;

contract Strudent{
    uint public uAge = 10;
    bool public uGender = false;
    
    function changeMsg(uint num,bool _uGender) public{
        uAge += num;
        uGender=_uGender;
    }

}

contract StuInfoManage{
    function callByFun(address addr) public returns (bool){
        bytes4 methodId = bytes4(keccak256("changeMsg(uint256,bool)"));
        return addr.call(methodId,10,true);
    }
}
  • 每一个合约有且仅有一个没有名字的函数。这个函数无参数,也无返回值。
  • 调用场景:

image.png