以太坊智能合约之转账原理

 在以太坊智能合约开发中,有时需要向智能合约地址直接转账,比如ico众筹, 目前有三种方式:

  • 创建合约时转账
  • 调用合约方法时转账
  • 直接向合约地址进行转账

创建合约时转账

    在进行合约开发时,如果想要在创建合约时直接向该合约进行转账,只需要给构造函数中添加payable修饰符
contract C {
    function C() payable{
    }
}

执行合约方法转账

    需要给你需要支持转账功能的方法添加payable修饰符

function d() payable {
    a = 3;
}

直接转账

    支持直接转账,需要借助默认函数(fallback function),默认函数是没有名字的函数,如下

function () payable {
    a = 3;
}

用户如何向智能合约转账

    用户向智能合约转账的核心是填充transaction.value的值,该值就是转账的金额,evm会执行先扣款后验证的逻辑,即不管对应的函数是否支持转账都会先扣除value实现转账,如果对应的函数不支持转账,对应的函数的代码会通过revert指令撤销前面的转账操作。具体原理看下面的Payable关键词原理

Payable关键词原理

    payable关键词是编译器支持的,函数是否带有payable关键词,编译器会生成不一样的代码。如果不带有payable关键词,会在函数的入口添加callvalue的检验。

构造函数不带payable标识

contract C {
function C() {
}
}
对应的汇编如下,创建智能合约时会检测callvalue是否为0,不为0,则非法参数会revert
.code
PUSH 80 contract C {\n function C()...
PUSH 40 contract C {\n function C()...
MSTORE contract C {\n function C()...
CALLVALUE function C() {\n }
DUP1 C {\n
ISZERO ac
PUSH [tag] 1 ac
JUMPI ac
PUSH 0 {
DUP1 (
REVERT ction C() {\n

如果带上payable

contract C {
function C() payable{
}
}
.code
PUSH 80 contract C {\n function C()...
PUSH 40 contract C {\n function C()...
MSTORE contract C {\n function C()...
PUSH #[$] 0000000000000000000000000000000000000000000000000000000000000000 contract C {\n function C()...
DUP1 contract C {\n function C()...
PUSH [$] 0000000000000000000000000000000000000000000000000000000000000000 contract C {\n function C()...
PUSH 0 contract C {\n function C()...
CODECOPY contract C {\n function C()...
PUSH 0 contract C {\n function C()...
RETURN contract C {\n function C()...
不检测callvalue, 也没有revert

普通函数的payable

    普通函数是一样的,如果没有加payable, 每个函数入口都会检测CALLVALUE
function d() {
a = 3;
}
tag 3 function d() {\n a = 3;...
JUMPDEST function d() {\n a = 3;...
CALLVALUE function d() {\n a = 3;...
DUP1 C {\n
ISZERO ac
PUSH [tag] 8 ac
JUMPI ac
PUSH 0 c
DUP1 b
REVERT t256 public

有callvalue及revert指令

fallback函数payable

function() {
a = 0x4f;
}
tag 1 contract C {\n uint256 publ...
JUMPDEST contract C {\n uint256 publ...
CALLVALUE contract C {\n uint256 publ...
DUP1 C {\n
ISZERO ac
PUSH [tag] 5 ac
JUMPI ac
PUSH 0 c
DUP1 b
REVERT t256 public
tag 5 ac
JUMPDEST ac
POP
PUSH 4F 0x4f
PUSH 0 a
SSTORE a = 0x4f
STOP contract C {\n uint256 publ...
如果带上payable
function() payable{
a = 0x4f;
}
tag 1 contract C {\n uint256 publ...
JUMPDEST contract C {\n uint256 publ...
PUSH 4F 0x4f
PUSH 0 a
SSTORE a = 0x4f
STOP contract C {\n

/********************************

* 本文来自CSDN博主"爱踢门"
* 转载请标明出处 : http://blog.csdn.net/itleaks
******************************************/

猜你喜欢

转载自blog.csdn.net/itleaks/article/details/80319158