Transaction Hash:
Block:
15731396 at Oct-12-2022 10:20:35 AM +UTC
Transaction Fee:
0.001100955273692352 ETH
$2.49
Gas Used:
56,512 Gas / 19.481796321 Gwei
Emitted Events:
254 |
Invoice.PaymentAccepted( hash=CFAAD9620512BEFACC45041897C33213BC056372058DA43C2B76019CE67B46DF, tokenContract=0x00000000...000000000, time=1665570035, value=150030000000000000 )
|
Account State Difference:
Address | Before | After | State Difference | ||
---|---|---|---|---|---|
0x52dE8D3f...2B80DCf12 | (BitPay: Invoice 2) | 80.162406000000000035 Eth | 80.312436000000000035 Eth | 0.15003 | |
0xDAFEA492...692c98Bc5
Miner
| (Flashbots: Builder) | 1.385539979222778838 Eth | 1.385732250659478294 Eth | 0.000192271436699456 | |
0xeD832E6E...6A1fC7184 |
0.153750355635209638 Eth
Nonce: 824
|
0.002619400361517286 Eth
Nonce: 825
| 0.151130955273692352 |
Execution Trace
ETH 0.15003
Invoice.pay( value=150030000000000000, gasPrice=19481796321, expiration=1665572084, payload=0A72D60EADBD8736647AC8C20E0140D7034C5D9D28577752C8C813165C87B79B, hash=CFAAD9620512BEFACC45041897C33213BC056372058DA43C2B76019CE67B46DF, v=27, r=35F14AFBD12B0AA25CE9E4D2BD8A163EE49C674A2BAE12242ABA234B00E1141A, s=1066B950024EF3DE47AA20EC46ED388669C8064EAD836FF3B3940DA82659A0C7, tokenContract=0x0000000000000000000000000000000000000000 )
-
Null: 0x000...001.bbfc44d4( )
{"IERC20.sol":{"content":"pragma solidity ^0.4.23;\n\ncontract IERC20 {\n function totalSupply() public constant returns (uint);\n function balanceOf(address tokenOwner) public constant returns (uint balance);\n function allowance(address tokenOwner, address spender) public constant returns (uint remaining);\n function transfer(address to, uint tokens) public returns (bool success);\n function approve(address spender, uint tokens) public returns (bool success);\n function transferFrom(address from, address to, uint tokens) public returns (bool success);\n\n event Transfer(address indexed from, address indexed to, uint tokens);\n event Approval(address indexed tokenOwner, address indexed spender, uint tokens);\n}\n"},"Invoice_old.sol":{"content":"pragma solidity ^0.4.23;\n\nimport \"./IERC20.sol\";\n\n\ncontract Invoice {\n address public owner;\n address public quoteSigner;\n mapping(bytes32 =\u003e bool) public isPaid;\n\n event PaymentAccepted(bytes32 indexed hash, address indexed tokenContract, uint time, uint value);\n\n\n constructor(address valueSigner) public {\n owner = msg.sender;\n quoteSigner = valueSigner;\n }\n\n function isValidPayment(\n uint value,\n uint gasPrice,\n uint expiration,\n bytes32 payload,\n bytes32 hash,\n uint8 v,\n bytes32 r,\n bytes32 s,\n address tokenContract\n ) public view returns(bool valid) {\n bool isValid = !isPaid[payload];\n isValid = isValid \u0026\u0026 block.timestamp \u003c= expiration;\n isValid = isValid \u0026\u0026 tx.gasprice \u003e= gasPrice;\n bytes memory prefix = \"\\x19Ethereum Signed Message:\\n32\";\n bytes32 ourHash = keccak256(abi.encodePacked(value, gasPrice, expiration, payload, tokenContract));\n bytes32 payloadHash = keccak256(abi.encodePacked(prefix, ourHash));\n isValid = isValid \u0026\u0026 ourHash == hash;\n isValid = isValid \u0026\u0026 (ecrecover(payloadHash, v, r, s) == quoteSigner);\n return isValid;\n }\n\n function validatePayment(\n uint value,\n uint gasPrice,\n uint expiration,\n bytes32 payload,\n bytes32 hash,\n uint8 v,\n bytes32 r,\n bytes32 s,\n address tokenContract\n ) public view returns(bool valid) {\n require(isPaid[payload] == false, \"Already been paid\");\n require(block.timestamp \u003c= expiration, \"Payment is late\");\n require(tx.gasprice \u003e= gasPrice, \"Gas price lower than required\");\n bytes memory prefix = \"\\x19Ethereum Signed Message:\\n32\";\n bytes32 ourHash = keccak256(abi.encodePacked(value, gasPrice, expiration, payload, tokenContract));\n bytes32 payloadHash = keccak256(abi.encodePacked(prefix, ourHash));\n require(ourHash == hash, \"Hash mismatch\");\n require(ecrecover(payloadHash, v, r, s) == quoteSigner, \"Signature mismatch for quote\");\n return true;\n }\n\n\n function pay(\n uint value,\n uint gasPrice,\n uint expiration,\n bytes32 payload,\n bytes32 hash,\n uint8 v,\n bytes32 r,\n bytes32 s,\n address tokenContract\n ) public payable {\n if(tokenContract == 0x0) {\n require(validatePayment(msg.value, gasPrice, expiration, payload, hash, v, r, s, tokenContract), \"Only accept valid payments\");\n } else {\n IERC20 token = IERC20(tokenContract);\n require(token.allowance(msg.sender, address(this)) \u003e= value, \"Must have enough tokens to pay\");\n require(validatePayment(value, gasPrice, expiration, payload, hash, v, r, s, tokenContract), \"Only accept valid payments\");\n require(token.transferFrom(msg.sender, address(this), value), \"Transfer must succeed\");\n }\n isPaid[payload] = true;\n emit PaymentAccepted(hash, tokenContract, block.timestamp, value);\n }\n\n modifier isAdmin() {\n require(msg.sender == owner, \"Must be the contract owner\");\n _;\n }\n\n function withdraw(address tokenContract) public isAdmin {\n if(tokenContract == 0x0) {\n owner.transfer(address(this).balance);\n } else {\n IERC20 token = IERC20(tokenContract);\n uint balance = token.balanceOf(address(this));\n require(token.transfer(owner, balance), \"Must succeed withdrawing tokens\");\n }\n }\n\n function setSigner(address newQuoteSigner) public isAdmin {\n quoteSigner = newQuoteSigner;\n }\n function setAdmin(address newAdmin) public isAdmin {\n owner = newAdmin;\n }\n}\n\n"}}