solidity自学:第三天

目录

使用钱包转移资金

 合约与合约账户

transfer转移资金 

 以太坊中的全局属性

转账误操作

底层sender方法

mapping映射——哈希表

 函数重载

函数命名参数

返回值

constant

构造函数

modifier

继承inherit

多重继承 

 全局变量自动getter函数

合约的销毁


使用钱包转移资金

 

 当调用pay函数的时候(pay函数必须实现payable),会向该合约地址发送10个以太币。

用户从99 ehter变成89 ether。

payable :代表我们可以通过这个函数来给我们的合约地址充值、转账

    function pay() payable{
    }
    function getBalance() returns(uint){
        return this.balance;//获取本合约的余额
    }

 合约与合约账户

    //账户地址:0x5B38Da6a701c568545dCfcB03FcB875f56beddC4
    //合约地址:0xDA0bab807633f07f013f94DD0E6A4F96F8742B53
    function getThis() view returns(address){
        return this;
        //返回0xDA0bab807633f07f013f94DD0E6A4F96F8742B53
        //这说明了this表示本合约的地址
        //balanace是this里面的一个属性
    }

    function getRandomBalance() view returns(uint){
        //获得任意一个地址(账户/合约)的金额
        address account = 0x5B38Da6a701c568545dCfcB03FcB875f56beddC4;
        return account.balance;
    }

transfer转移资金 

    //外部地址与外部地址之间的转账
// msg.value是用户,account1.transfer是合约地址。
    function transfer() payable{
        //向合约account1转入一笔钱
        address account1 = 0x78731D3Ca6b7E34aC0F824c42a7cC18A495cabaB;
        //意思是目前的合约会向account1转账:将VALUE设置为10,然后调用transfer
        //本合约:0x5B38Da6a701c568545dCfcB03FcB875f56beddC4从89变为79
        //account1:0x78731D3Ca6b7E34aC0F824c42a7cC18A495cabaB从99变成109
        account1.transfer(msg.value);
    }
    function transfer2() payable{
        this.transfer(msg.value);
    }
    function () payable{
        //回滚函数
    }

 以太坊中的全局属性

msg对象代表调用合约时传递的消息内容。

  • msg.data (bytes):完整的calldata。完整的调用数据(calldata)
  • msg.gas (uint):剩余的gas量
  • msg.sender (address):消息的发送方(合约的调用者,也就是用户)
  • msg.sig (bytes4):calldata的前四个字节(即函数标识符)
  • msg.value (uint):联盟链中无需使用此数据。这个信息所附带的以太币,单位wei
  • block.difficulty(uint):当前块的难度
  • block.number(uint):当前块的块号
  • block.coinbase(address):当前块矿工的地址(也就是这个块是谁挖出来的)
  • now(uint):当前块的时间戳(block.timestamp的别名).
        function getGlobal1() view returns(address){
            return msg.sender;
            //返回0x5B38Da6a701c568545dCfcB03FcB875f56beddC4
        }
        function getGlobal2() view returns(uint){
            return block.difficulty;
            //返回69762765929000
        }
        function getGlobal3() view returns(uint){
            return block.number;
            //返回15。该区块不会变化
        }

转账误操作

如果函数实现了payable,但是里面没有指定地址,那么VALUE的默认地址就是本合约的地址

function transfer() payable{}

 奇怪的现象:VALUE设置为20,而transfer()设置为10。运行之后,目标用户地址+10,用户-20,而少了的10则去到了合约地址当中

    function transfer() payable{
        //account是目标用户地址
        address account = 0x5B38Da6a701c568545dCfcB03FcB875f56beddC4;
        account.transfer(10 ether);
    }

底层sender方法

transfer方法,如果什么都不传递进去,那么会报错。sender方法,什么都不传递进去也都可以运行,但是不会成功转账,它是一个底层函数,存在安全危险!sender的返回值是bool。

send()方法执行时有一些风险:

  • 调用递归深度不能超过1024
  • 如果gas不够,执行会失败
  • 所以使用这个方法要检查成功与否
  • transfer相对send较安全 ,所以以后用transfer更好

mapping映射——哈希表

pragma solidity ^0.4.4;

contract mappingTest{
    //是一对一 一一对应的关系
    //                 id
    mapping(address => uint) idMapping;
    //本用户:0x5B38Da6a701c568545dCfcB03FcB875f56beddC4 => 1
    mapping(uint => string) nameMapping;
    //1 => "陈钦"

    uint sum = 0;//用于编号

    function register(string name){
        address account_ = msg.sender;
        sum++;
        //mapping(address => uint) idMapping:account_会加入到address,sum加入到uint
        idMapping[account_] = sum;
        //mapping(uint => string) nameMapping:sum会加入到uint,name会加入到string
        nameMapping[sum] = name;
    }
    function getIdByAddress(address x) view returns(uint){
        return idMapping[x];
    }
    function getNameById(uint x) view returns(string){
        return nameMapping[x];
    }
}

 函数重载

以下代码test1(123)发生了错误,因为address和uint160在solidity处理的时候都是一样的,按照uint160处理。无法匹配到对应的test1.两个函数虽然可以编译通过,但是无法调用

    function test1(address _x){}
    function test1(uint160 _x){}
    function test(){
        test1(123);
    }

函数命名参数

参数的传入可以不按照顺序,用下面的方法来写

    function test(){
        setGuy({_name:"123",_phone:6164665});
    }

返回值

风骚的返回方式

    function returntest() returns(uint mul){
        mul = 1;
        //return 5;  如果此时有这句话,则返回5,否则返回1
    }

多返回值

    function t(uint a,uint b) view returns(uint add,uint mul){
        add = a + b;
        mul = a * b;
        //return(a+b,a*b);  是同样的效果
    }

constant

在4.0版本中和view等价,5.0版本中被废弃。局部变量中无法使用constant

uint public constant num = 50;   =====>  全局变量无法被修改

4.0版本中,支持int, uint, string ,bytes1…bytes32使用constant

构造函数

构造函数只能有一个(和Java不一样!!!)

    function constructor_(){
        a = 100;
    }
//新版本的solidity的构造器如下写法:
    constructor(){//默认是public
        a = 100;
    }

modifier

相当于一个判断条件,将判断封装起来

contract modifier_{
    address public owner;
    uint public num = 0;

    constructor(){
        owner = msg.sender;
    }

    modifier OnlyOwner{
        require(msg.sender == owner);
        _;
    }

    function changeIt(uint _num) OnlyOwner{
        num = _num;
    }
}
    uint public level = 0;
    modifier level(uint needLevel){
        require(level >= needLevel);
        _;
    }
    function changeId() level(2){}
    function changeName() level(10){}

 多重modifier

    modifier mod1{
        a = 1;
        _;
        a = 2;
    }
    modifier mod2{
        a = 3;
        _;
        a = 4;
    }
    function m() mod1 mod2{
        a = 100
    }//执行结果:a = 2
    //过程:a = 1,a = 3, a = 100 ,a = 4, a = 2

继承inherit

格式:contract A is B{}         A是孩子,B是双亲

public, interal, external, private中,只有private修饰的不可以被继承

  • external:只可以在外部调用,可以被继承
  • internal:只可以在内部调用,可以被继承
  • private:只可以在内部调用,不可以被继承

特殊的,external可以这么调用

    function dahan() external pure returns(string){}
    function dahanTest() public view{
        this.dahan();//这里相当于外部调用
    }

或者在外部合约中new一个内部合约,然后调用该方法

多重继承 

contract son is dad, mom{}

这个合约是覆盖继承,如果dad和mom有重复的属性或者方法,mom作为后者会覆盖dad前者,在合约son中显示mom的属性或者方法

 全局变量自动getter函数

public会自动生成getter函数

比如:uint public num = 1;

           此时相当于写了下面这个函数:

           function num() external view returns(uint){ return num;}

 比如:mapping(uint => string) public map;

          此时相当于写了下面这个函数:

          function map(uint key) external returns(string){}

 疯狂的映射:这里在mapping方法中输入0,3,20,则输出陈钦

    mapping(uint => mapping(uint => mapping(uint => string))) public map;
    function test(){
        map[0][3][20] = "陈钦";
    }

合约的销毁

使用selfdestruct()来销毁

pragma solidity ^0.4.0;

contract destruction{
    address owner;
    uint public money = 0;

    constructor(){
        owner = msg.sender;
    }

    function increment(){
        money += 10;
    }
    function kill(){
        if(msg.sender == owner){
            selfdestruct(owner);
        }
    }
}

猜你喜欢

转载自blog.csdn.net/weixin_62775913/article/details/125500401