|
| 1 | +from cytoolz import ( |
| 2 | + assoc, |
| 3 | +) |
| 4 | +from tests.core.helpers import ( |
| 5 | + new_transaction, |
| 6 | +) |
| 7 | + |
| 8 | +from eth_utils import ( |
| 9 | + decode_hex, |
| 10 | + function_signature_to_4byte_selector, |
| 11 | + to_bytes, |
| 12 | +) |
| 13 | +import pytest |
| 14 | + |
| 15 | +from eth.exceptions import ( |
| 16 | + InvalidInstruction, |
| 17 | + OutOfGas, |
| 18 | +) |
| 19 | + |
| 20 | + |
| 21 | +@pytest.fixture |
| 22 | +def chain(chain_with_block_validation): |
| 23 | + return chain_with_block_validation |
| 24 | + |
| 25 | + |
| 26 | +@pytest.fixture |
| 27 | +def simple_contract_address(): |
| 28 | + return b'\x88' * 20 |
| 29 | + |
| 30 | + |
| 31 | +@pytest.fixture |
| 32 | +def genesis_state(base_genesis_state, simple_contract_address): |
| 33 | + """ |
| 34 | + Includes runtime bytecode of compiled Solidity: |
| 35 | +
|
| 36 | + pragma solidity ^0.4.24; |
| 37 | +
|
| 38 | + contract GetValues { |
| 39 | + function getMeaningOfLife() public pure returns (uint256) { |
| 40 | + return 42; |
| 41 | + } |
| 42 | + function getGasPrice() public view returns (uint256) { |
| 43 | + return tx.gasprice; |
| 44 | + } |
| 45 | + function getBalance() public view returns (uint256) { |
| 46 | + return msg.sender.balance; |
| 47 | + } |
| 48 | + function doRevert() public pure { |
| 49 | + revert("always reverts"); |
| 50 | + } |
| 51 | + function useLotsOfGas() public view { |
| 52 | + uint size; |
| 53 | + for (uint i = 0; i < 2**255; i++){ |
| 54 | + assembly { |
| 55 | + size := extcodesize(0) |
| 56 | + } |
| 57 | + } |
| 58 | + } |
| 59 | + } |
| 60 | + """ |
| 61 | + return assoc( |
| 62 | + base_genesis_state, |
| 63 | + simple_contract_address, |
| 64 | + { |
| 65 | + 'balance': 0, |
| 66 | + 'nonce': 0, |
| 67 | + 'code': decode_hex('60806040526004361061006c5763ffffffff7c010000000000000000000000000000000000000000000000000000000060003504166312065fe08114610071578063455259cb14610098578063858af522146100ad57806395dd7a55146100c2578063afc874d2146100d9575b600080fd5b34801561007d57600080fd5b506100866100ee565b60408051918252519081900360200190f35b3480156100a457600080fd5b506100866100f3565b3480156100b957600080fd5b506100866100f7565b3480156100ce57600080fd5b506100d76100fc565b005b3480156100e557600080fd5b506100d7610139565b333190565b3a90565b602a90565b6000805b7f80000000000000000000000000000000000000000000000000000000000000008110156101355760003b9150600101610100565b5050565b604080517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152600e60248201527f616c776179732072657665727473000000000000000000000000000000000000604482015290519081900360640190fd00a165627a7a72305820645df686b4a16d5a69fc6d841fc9ad700528c14b35ca5629e11b154a9d3dff890029'), # noqa: E501 |
| 68 | + 'storage': {}, |
| 69 | + }, |
| 70 | + ) |
| 71 | + |
| 72 | + |
| 73 | +def uint256_to_bytes(uint): |
| 74 | + return to_bytes(uint).rjust(32, b'\0') |
| 75 | + |
| 76 | + |
| 77 | +@pytest.mark.parametrize( |
| 78 | + 'signature, gas_price, expected', |
| 79 | + ( |
| 80 | + ( |
| 81 | + 'getMeaningOfLife()', |
| 82 | + 0, |
| 83 | + uint256_to_bytes(42), |
| 84 | + ), |
| 85 | + ( |
| 86 | + 'getGasPrice()', |
| 87 | + 0, |
| 88 | + uint256_to_bytes(0), |
| 89 | + ), |
| 90 | + ( |
| 91 | + 'getGasPrice()', |
| 92 | + 9, |
| 93 | + uint256_to_bytes(9), |
| 94 | + ), |
| 95 | + ( |
| 96 | + # make sure that whatever voodoo is used to execute a call, the balance is not inflated |
| 97 | + 'getBalance()', |
| 98 | + 1, |
| 99 | + uint256_to_bytes(0), |
| 100 | + ), |
| 101 | + ), |
| 102 | +) |
| 103 | +def test_get_transaction_result( |
| 104 | + chain, |
| 105 | + simple_contract_address, |
| 106 | + signature, |
| 107 | + gas_price, |
| 108 | + expected): |
| 109 | + |
| 110 | + function_selector = function_signature_to_4byte_selector(signature) |
| 111 | + call_txn = new_transaction( |
| 112 | + chain.get_vm(), |
| 113 | + b'\xff' * 20, |
| 114 | + simple_contract_address, |
| 115 | + gas_price=gas_price, |
| 116 | + data=function_selector, |
| 117 | + ) |
| 118 | + result_bytes = chain.get_transaction_result(call_txn, chain.get_canonical_head()) |
| 119 | + assert result_bytes == expected |
| 120 | + |
| 121 | + |
| 122 | +@pytest.mark.parametrize( |
| 123 | + 'signature, expected', |
| 124 | + ( |
| 125 | + ( |
| 126 | + 'doRevert()', |
| 127 | + InvalidInstruction, |
| 128 | + ), |
| 129 | + ( |
| 130 | + 'useLotsOfGas()', |
| 131 | + OutOfGas, |
| 132 | + ), |
| 133 | + ), |
| 134 | +) |
| 135 | +def test_get_transaction_result_revert( |
| 136 | + chain, |
| 137 | + simple_contract_address, |
| 138 | + signature, |
| 139 | + expected): |
| 140 | + |
| 141 | + function_selector = function_signature_to_4byte_selector(signature) |
| 142 | + call_txn = new_transaction( |
| 143 | + chain.get_vm(), |
| 144 | + b'\xff' * 20, |
| 145 | + simple_contract_address, |
| 146 | + data=function_selector, |
| 147 | + ) |
| 148 | + with pytest.raises(expected): |
| 149 | + chain.get_transaction_result(call_txn, chain.get_canonical_head()) |
0 commit comments