Solidity 是一门面向合约的、为实现智能合约而创立的高级编程语言,为了体验Solidity语言在智能合约利用场景广泛性,跟着Solidity官网文档和中文社区学习做两个简略例子以相熟装置、配置、应用集成开发环境和根底智能合约理论利用。
规范以太坊货币例子合约相熟开发环境
任何语言都一样,让咱们来疾速体验一下Solidity的helloworld吧,把前几天学到的货币合同copy来间接上环境一睹为快:
- 拜访https://remix.ethereum.org/网站,初始加载比较慢,能够轻易点点最右边的图标看看有些什么性能;
- 点File explorers在default_workspace边上,点Create创立一个新空间workspace_mark;点Create New File在contracts下创立一个合约;
- 将如下代码保留在合约中;
pragma solidity ^0.4.16;interface tokenRecipient { function receiveApproval(address _from, uint256 _value, address _token, bytes _extraData) external; }contract t_first_Token { string public name; string public symbol; uint8 public decimals = 18; // 18 是倡议的默认值 uint256 public totalSupply; mapping (address => uint256) public balanceOf; // mapping (address => mapping (address => uint256)) public allowance; event Transfer(address indexed from, address indexed to, uint256 value); event Burn(address indexed from, uint256 value); function t_first_Token(uint256 initialSupply, string tokenName, string tokenSymbol) public { totalSupply = initialSupply * 10 ** uint256(decimals); balanceOf[msg.sender] = totalSupply; name = tokenName; symbol = tokenSymbol; } function _transfer(address _from, address _to, uint _value) internal { require(_to != 0x0); require(balanceOf[_from] >= _value); require(balanceOf[_to] + _value > balanceOf[_to]); uint previousBalances = balanceOf[_from] + balanceOf[_to]; balanceOf[_from] -= _value; balanceOf[_to] += _value; Transfer(_from, _to, _value); assert(balanceOf[_from] + balanceOf[_to] == previousBalances); } function transfer(address _to, uint256 _value) public returns (bool) { _transfer(msg.sender, _to, _value); return true; } function transferFrom(address _from, address _to, uint256 _value) public returns (bool success) { require(_value <= allowance[_from][msg.sender]); // Check allowance allowance[_from][msg.sender] -= _value; _transfer(_from, _to, _value); return true; } function approve(address _spender, uint256 _value) public returns (bool success) { allowance[msg.sender][_spender] = _value; return true; } function approveAndCall(address _spender, uint256 _value, bytes _extraData) public returns (bool success) { tokenRecipient spender = tokenRecipient(_spender); if (approve(_spender, _value)) { spender.receiveApproval(msg.sender, _value, this, _extraData); return true; } } function burn(uint256 _value) public returns (bool success) { require(balanceOf[msg.sender] >= _value); balanceOf[msg.sender] -= _value; totalSupply -= _value; Burn(msg.sender, _value); return true; } function burnFrom(address _from, uint256 _value) public returns (bool success) { require(balanceOf[_from] >= _value); require(_value <= allowance[_from][msg.sender]); balanceOf[_from] -= _value; allowance[_from][msg.sender] -= _value; totalSupply -= _value; Burn(_from, _value); return true; }}
- 抉择Solidity Compiler出新界面后,点击Compile t_first_token.sol编译智能合同,点击Publish on Swarm将智能合同发表;
- Deploy按下图三步公布合同到JavaScript vm中;
公布初始结构须要货币总量、币名和币编号。
- 操作JavaScript vm中合同的函数并查问变量;
应用MetaMask钱包等的地址0x7a7644C0F817eb94C823781E20B2F2EcE2916967调用(JavaScript vm要进行格局验证)。
- 这样Solidity编辑的智能合同,一个仿以太币就show进去了。
合同间调用例子看智能合约的变动
- 学习生产环境的配置看考Hardhat + VS code(https://www.yuque.com/bernieg...)文档
装置运行hardhat:
npm install --save-dev @nomiclabs/hardhat-waffle ethereum-waffle chai @nomiclabs/hardhat-ethers ethers
npx hardhat
由上到下运行如下命令:
npx hardhat accounts
npx hardhat compile
npx hardhat test
npx hardhat node
node scripts/sample-script.js
npx hardhat help
npx hardhat test能够失去真正的helloworld合同输入
Deploying a Greeter with greeting: Hello, world!
Changing greeting from 'Hello, world!' to 'Hola, mundo!'
npx hardhat node
Started HTTP and WebSocket JSON-RPC server at http://127.0.0.1:8545/
- 将下面t_first_token.sol合同转移到hardhat环境中运行
合同降级到0.7+,批改相应代码如下( //批改版本升级)
-wanning:加license标签,constrctor 去掉public润饰
-error:版本,加memory润饰,比拟adress,this 被adress强制转换等
//SPDX-License-Identifier: Unlicense //批改版本升级pragma solidity >=0.7.0;//批改版本升级interface tokenRecipient { function receiveApproval(address _from, uint256 _value, address _token, bytes memory _extraData) external; //批改版本升级 }contract t_first_token { string public name; string public symbol; uint8 public decimals = 18; // 18 是倡议的默认值 uint256 public totalSupply; mapping (address => uint256) public balanceOf; // mapping (address => mapping (address => uint256)) public allowance; event Transfer(address indexed from, address indexed to, uint256 value); event Burn(address indexed from, uint256 value); //function t_first_token(uint256 initialSupply, string memory tokenName, string memory tokenSymbol) public {constructor(uint256 initialSupply, string memory tokenName, string memory tokenSymbol) {//批改版本升级 totalSupply = initialSupply * 10 ** uint256(decimals); balanceOf[msg.sender] = totalSupply; name = tokenName; symbol = tokenSymbol; } function _transfer(address _from, address _to, uint _value) internal { require(_to != 0x0000000000000000000000000000000000000000);//批改版本升级 require(balanceOf[_from] >= _value); require(balanceOf[_to] + _value > balanceOf[_to]); uint previousBalances = balanceOf[_from] + balanceOf[_to]; balanceOf[_from] -= _value; balanceOf[_to] += _value; emit Transfer(_from, _to, _value); assert(balanceOf[_from] + balanceOf[_to] == previousBalances); } function transfer(address _to, uint256 _value) public returns (bool) { _transfer(msg.sender, _to, _value); return true; } function transferFrom(address _from, address _to, uint256 _value) public returns (bool success) { require(_value <= allowance[_from][msg.sender]); // Check allowance allowance[_from][msg.sender] -= _value; _transfer(_from, _to, _value); return true; } function approve(address _spender, uint256 _value) public returns (bool success) { allowance[msg.sender][_spender] = _value; return true; } function approveAndCall(address _spender, uint256 _value, bytes memory _extraData) public returns (bool success) {//批改版本升级 tokenRecipient spender = tokenRecipient(_spender); if (approve(_spender, _value)) { spender.receiveApproval(msg.sender, _value, address(this), _extraData);//批改版本升级 return true; } } function burn(uint256 _value) public returns (bool success) { require(balanceOf[msg.sender] >= _value); balanceOf[msg.sender] -= _value; totalSupply -= _value; emit Burn(msg.sender, _value); return true; } function burnFrom(address _from, uint256 _value) public returns (bool success) { require(balanceOf[_from] >= _value); require(_value <= allowance[_from][msg.sender]); balanceOf[_from] -= _value; allowance[_from][msg.sender] -= _value; totalSupply -= _value; emit Burn(_from, _value); return true; }}
3.增加计数合同,更新t_first_token.sol增加变量
test测试合同中的函数调用
const { expect } = require("chai");describe("Greeter", function() { it("Should return the new greeting once it's changed", async function() { const Greeter = await ethers.getContractFactory("Greeter"); const greeter = await Greeter.deploy("Hello, world!"); await greeter.deployed(); expect(await greeter.greet()).to.equal("Hello, world!"); const setGreetingTx = await greeter.setGreeting("Hola, mundo!"); // wait until the transaction is mined await setGreetingTx.wait(); expect(await greeter.greet()).to.equal("Hola, mundo!"); });});describe("t_first_token", function() { it("Should return mane", async function() { const _t_first_token = await ethers.getContractFactory("t_first_token"); const t_first_token = await _t_first_token.deploy(2000,"markcion","18188"); await t_first_token.deployed(); expect(t_first_token.burn(111)); });});describe("t_first_token/Greeter", function() { it("Should return t_first_token/Greeter", async function() { const _t_first_token = await ethers.getContractFactory("t_first_token"); const t_first_token = await _t_first_token.deploy(2000,"markcion","18188"); await t_first_token.deployed(); const Greeter = await ethers.getContractFactory("Greeter"); const greeter = await Greeter.deploy("Hello, world!"); await greeter.deployed(); expect(t_first_token.inc()); expect(greeter.inc()); expect(greeter.inc()); });});
npx hardhat test
Greeter
Deploying a Greeter with greeting: Hello, world!
Changing greeting from 'Hello, world!' to 'Hola, mundo!'
✓ Should return the new greeting once it's changed (1098ms)
t_first_token
Deploying a tokenName: markcion
✓ Should return mane (122ms)
t_first_token/Greeter
burn-totalSupply: 1999999999999999999889
Deploying a tokenName: markcion
t_first_token m: 2
Deploying a Greeter with greeting: Hello, world!
✓ Should return t_first_token/Greeter (173ms)
3 passing (1s)
Greeter m: 2
Greeter m: 3
- 调用关系并简略剖析
在Solidity中,如果只是为了代码复用,咱们会把公共代码抽出来,部署到一个library中,前面就能够像调用C库、Java库一样应用了。然而library中不容许定义任何storage类型的变量,这就意味着library不能批改合约的状态。如果须要批改合约状态,咱们须要部署一个新的合约,这就波及到合约调用合约的状况。
合约调用合约有上面4种形式:
1) CALL
2) CALLCODE
3) DELEGATECALL
4) STATICCALL
CALL vs. CALLCODE
CALL和CALLCODE的区别在于:代码执行的上下文环境不同。
具体来说,CALL批改的是被调用者的storage,而CALLCODE批改的是调用者的storage。
CALLCODE vs. DELEGATECALL
实际上,能够认为DELEGATECALL是CALLCODE的一个bugfix版本,官网曾经不倡议应用CALLCODE了。
CALLCODE和DELEGATECALL的区别在于:msg.sender不同。
具体来说,DELEGATECALL会始终应用原始调用者的地址,而CALLCODE不会。
将钱包和合约买通(高阶 继续更新)
Solidity语言特点及学习差别列表 (继续更新)
- solidity语法注意事项
1)所有的标识符(合约名称,函数名称和变量名称)都只能应用ASCII字符集。UTF-8编码的数据能够用字符串变量的模式存储。(小心应用Unicode文本,因为有些字符尽管长得相像(甚至一样),但其字符码是不同的,其编码后的字符数组也会不一样。)
2)变量
uint (256位无符号整数),块的概念无处不在。
address 类型是一个160位的值,且不容许任何算数操作。这种类型适宜存储合约地址或内部人员的密钥对。
mapping (address => uint) 黑匣子哈希表(无key汇合拜访)。
3)合约版本变动,语法变化很大,应用编译版本限度。
4)“undefined”或“null”值的概念在Solidity中不存在,然而变量申明后将有默认初始值,其初始值字节示意全副为零。任何类型变量的“默认值”是其对应类型的典型“零状态”。例如, bool 类型的默认值是 false 。 uint 或 int 类型的默认值是 0 。对于动态大小的数组和 bytes1 到 bytes32 ,每个独自的元素将被初始化为与其类型绝对应的默认值。 最初,对于动静大小的数组 bytes 和 string 类型,其默认缺省值是一个空数组或空字符串。
欢送区块链行业气味相投的小伙伴增加小极微信,退出blockgeek区块链技术交换群,独特推动区块链技术遍及和倒退~