由于Solidity是基于以太坊(Ethereum)的,故而其语言层面可以直接支持货币支付1。
payable标识的函数
函数上增加payable
标识,即可接收ether,并会把ether存在当前合约,如下述示例中的deposit
函数。
pragma solidity ^0.4.0;
contract supportPay{
//存入一些ether用于后面的测试
function deposit() payable{
}
//查询当前的余额
function getBalance() constant returns(uint){
return this.balance;
}
}
在上面的代码中,你可以通过deposit()
向当前合约存入ether,注意这是通过函数调用,在调用中通过address.call(某个方法).value(要发送的ether)
来实现的,这里可以参考: http://me.tryblockchain.org/Solidity-call-callcode-delegatecall.html 。
send()函数发送ether
地址对象中的send()
可以向某地址直接进行支付,下面是一个向合约帐户支付的示例:
当我们使用address.send(ether to send)
向某个地址转帐,如果是普通地址将会直接收到,就非常简单了。我们这里将用合约来模拟发送与接收:
pragma solidity ^0.4.0;
contract SendAndReceiveByContract{
//fallback函数对应记录事件
event fallbackTrigged(bytes data);
//合约接收send()的 ether时,必须存在
function() payable{fallbackTrigged(msg.data);}
//存入一些ether用于后面的测试
function deposit() payable{
}
//查询当前的余额
function getBalance() constant returns(uint){
return this.balance;
}
event SendEvent(address to, uint value, bool result);
//使用send()发送ether
function sendEther(){
//使用this来模拟从另一个合约发送
bool result = this.send(1);
SendEvent(this, 1, result);
}
}
在上述的代码中,我们先要使用deposit()
合约存入一些ether,否则由于余额不足,调用send()
函数将报错。存入ether后,我们调用sendEther()
,使用send()
向合约发送数据,将会触发下述事件:
SendEvent[
"0xc35f7ac1351648b0b8a699c5f07dd6a78f626714",
"1",
"true"
]
fallbackTrigged[
"0x"
]
可以看到,我们成功使用send()
发送了1wei到合约。
这里需要特别注意的是,下面大家先记着,后面 http://me.tryblockchain.org/blockchain-solidity-fallback.html 会说明,合约要接收通过send()
函数发送的ether,有下面的限制:
- 如果我们要在合约中通过
send()
函数接收,就必须定义fallback函数,否则会抛异常。 - fallback函数必须增加
payable
关键字,否则send()
执行结果将会始终为false
。
支付中可能的失败
send()
失败
由于调用者可以强制指定调用堆栈的深度,当调用的栈深超过指定值时,一般是1024;或者接收地址处理支付过程中out of gas
。由于失败,此时的send()
的结果是false
。
合约的fallback()
如果是合约地址,在执行send()
时,会默认关联执行fallback()
(如果存在这个函数)。这是EVM的默认行为,不可被阻止。所以这个函数引起out of gas
或其它失败,整个交易被撤销。由于失败,此时的send()
的结果是false
。
payable标识2
细心的读者可能发现在deposit
函数上有一个payable
关键字,如果一个函数需要进行货币操作,必须要带上payable
关键字,这样才能正常接收msg.value
。
关于作者
专注基于以太坊(Ethereum)的相关区块链(Blockchain)技术,了解以太坊,Solidity,Truffle等。个人博客:http://me.tryblockchain.org
处于某些特定的环境下,可以看到评论框,欢迎留言交流^_^。