[native]'元交易'与'原生'的转账gas消耗测试
2021-10-21 本文已影响0人
95加不满
结果:transfer < metaTransferMy < metaTransfer
初步可以肯定:正常情况下metaTransfer不会达到transfer的2倍。(当然gas的消耗与执行的代码量有关。)
测试
- metaTransfer
to MetaCoin.metaTransfer(bytes,address,uint256,uint256,uint256) 0xd9145CCE52D386f254917e481eB44e9943F39138
gas 80000000 gas
transaction cost 50496 gas
execution cost 50496 gas
- metaTransferMy
- reward = 200
to MetaCoin.metaTransferMy(address,address,uint256,uint256) 0xd9145CCE52D386f254917e481eB44e9943F39138
gas 80000000 gas
transaction cost 38537 gas
execution cost 38537 gas
- reward = 0
to MetaCoin.metaTransferMy(address,address,uint256,uint256) 0xd9145CCE52D386f254917e481eB44e9943F39138
gas 80000000 gas
transaction cost 35376
execution cost 35376 gas
- transfer
to MetaCoin.transfer(address,uint256) 0xd9145CCE52D386f254917e481eB44e9943F39138
gas 80000000 gas
transaction cost 34961
execution cost 34961 gas
合约代码
pragma solidity ^0.4.24;
import "openzeppelin-solidity/contracts/token/ERC20/ERC20Mintable.sol";
contract MetaCoin is ERC20Mintable {
string public name = "MetaCoin";
string public symbol = "MC";
uint8 public decimals = 0;
constructor() public {
}
mapping (address => uint256) public replayNonce;
function metaTransfer(bytes signature, address to, uint256 value, uint256 nonce, uint256 reward) public returns (bool) {
bytes32 metaHash = metaTransferHash(to,value,nonce,reward);
address signer = getSigner(metaHash,signature);
//make sure signer doesn't come back as 0x0
require(signer!=address(0));
require(nonce == replayNonce[signer]);
replayNonce[signer]++;
_transfer(signer, to, value);
if(reward>0){
_transfer(signer, msg.sender, reward);
}
}
function metaTransferMy(address from, address to, uint256 value, uint256 reward) public returns (bool) {
_transfer(from, to, value);
if(reward>0){
_transfer(from, msg.sender, reward);
}
}
function metaTransferHash(address to, uint256 value, uint256 nonce, uint256 reward) public view returns(bytes32){
return keccak256(abi.encodePacked(address(this),"metaTransfer", to, value, nonce, reward));
}
/*
function metaApprove(address spender, uint256 value, uint256 nonce, uint256 reward, bytes signature) public returns (bool) {
require(spender != address(0));
bytes32 metaHash = metaApproveHash(spender,value,nonce,reward);
address signer = getSigner(metaHash,signature);
require(nonce == replayNonce[signer]);
replayNonce[signer]++;
_allowed[signer][spender] = value;
if(reward>0){
_transfer(signer, msg.sender, reward);
}
emit Approval(msg.sender, spender, value);
return true;
}
function metaApproveHash(address spender, uint256 value, uint256 nonce, uint256 reward) public view returns(bytes32){
return keccak256(abi.encodePacked(address(this),"metaApprove" spender, value, nonce, reward));
}
*/
function getSigner(bytes32 _hash, bytes _signature) public pure returns (address){
bytes32 r;
bytes32 s;
uint8 v;
if (_signature.length != 65) {
return address(0);
}
assembly {
r := mload(add(_signature, 32))
s := mload(add(_signature, 64))
v := byte(0, mload(add(_signature, 96)))
}
if (v < 27) {
v += 27;
}
if (v != 27 && v != 28) {
return address(0);
} else {
return ecrecover(keccak256(
abi.encodePacked("\x19Ethereum Signed Message:\n32", _hash)
), v, r, s);
}
}
}