关于solidity:Solidity入门1

43次阅读

共计 8691 个字符,预计需要花费 22 分钟才能阅读完成。

Solidity 是一门面向合约的、为实现智能合约而创立的高级编程语言,为了体验 Solidity 语言在智能合约利用场景广泛性,跟着 Solidity 官网文档和中文社区学习做两个简略例子以相熟装置、配置、应用集成开发环境和根底智能合约理论利用。

规范以太坊货币例子合约相熟开发环境

任何语言都一样,让咱们来疾速体验一下 Solidity 的 helloworld 吧,把前几天学到的货币合同 copy 来间接上环境一睹为快:

  1. 拜访 https://remix.ethereum.org/ 网站,初始加载比较慢,能够轻易点点最右边的图标看看有些什么性能;
  2. 点 File explorers 在 default_workspace 边上,点 Create 创立一个新空间 workspace_mark;点 Create New File 在 contracts 下创立一个合约;

  1. 将如下代码保留在合约中;
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;
    }
}
  1. 抉择 Solidity Compiler 出新界面后,点击 Compile t_first_token.sol 编译智能合同,点击 Publish on Swarm 将智能合同发表;
  2. Deploy 按下图三步公布合同到 JavaScript vm 中;
    公布初始结构须要货币总量、币名和币编号。

  1. 操作 JavaScript vm 中合同的函数并查问变量;
    应用 MetaMask 钱包等的地址 0x7a7644C0F817eb94C823781E20B2F2EcE2916967 调用(JavaScript vm 要进行格局验证)。

  1. 这样 Solidity 编辑的智能合同,一个仿以太币就 show 进去了。

合同间调用例子看智能合约的变动

  1. 学习生产环境的配置看考 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/

  1. 将下面 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

  1. 调用关系并简略剖析
    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 语言特点及学习差别列表(继续更新)

  1. 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 区块链技术交换群,独特推动区块链技术遍及和倒退~

正文完
 0