Skip to content

Commit 264843f

Browse files
committed
Add tests for custom codecs
1 parent f0a3b3d commit 264843f

16 files changed

+832
-228
lines changed

docs/contracts.rst

Lines changed: 169 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -491,6 +491,175 @@ and the arguments are ambiguous.
491491
1
492492
493493
494+
Enabling Strict Checks for Bytes Types
495+
--------------------------------------
496+
497+
By default, web3 is not very strict when it comes to hex and bytes values.
498+
A bytes type will take a hex string, a bytestring, or a regular python
499+
string that can be decoded as a hex.
500+
Additionally, if an abi specifies a byte size, but the value that gets
501+
passed in is less than the specified size, web3 will automatically pad the value.
502+
For example, if an abi specifies a type of ``bytes4``, web3 will handle all of the following values:
503+
504+
.. code-block:: python
505+
506+
- '' # valid - empty string less than 4 bytes and can be decoded as a hex string
507+
- '0x' # valid - empty hex string
508+
- b'' # valid - empty bytestring
509+
- b'ab' # valid - less than 4 bytes
510+
- '0xab' # valid - hex string with less than 4 bytes
511+
- '1234' # valid - string that can be decoded as a hex string
512+
- '0x61626364' # valid - hex string with exactly 4 bytes
513+
- b'1234' # valid - bytestring with exactly 4 bytes
514+
515+
The following values will raise an error by default:
516+
517+
.. code-block:: python
518+
519+
- b'abcde' # invalid - more than 4 bytes
520+
- '0x6162636423' # invalid - hex string with more than 4 bytes
521+
- 2 # invalid - wrong type
522+
- 'ah' # invalid - string not valid hex
523+
524+
However, you may want to be stricter with acceptable values for bytes types.
525+
For this you can use the ``enable_strict_bytes_type_checking`` method,
526+
which is available on the w3 instance. When the method is called, a new codec is
527+
instatntiated and any string that is not prefixed with
528+
``0x`` will throw an error. Similarly, a bytestring that is less than the
529+
specified byte size will raise an error. Using the same ``bytes4`` example:
530+
531+
.. code-block:: python
532+
533+
- '0x61626364' # valid - hex string with exactly 4 bytes
534+
- b'1234' # valid - bytestring with exactly 4 bytes
535+
- b'ab' # invalid - less than 4 bytes
536+
- '0xab' # invalid - hex string with less than 4 bytes
537+
- '' # invalid - needs a 0x to be interpreted as hex
538+
- '1234' # invalid - needs a 0x to be interpreted as hex
539+
- b'' # invalid - less than 4 bytes
540+
- b'abcde' # invalid - more than 4 bytes
541+
- '0x6162636423' # invalid - hex string with more than 4 bytes
542+
- 2 # invalid - wrong type
543+
- 'ah' # invalid - string not valid hex
544+
545+
546+
For example, the following contract code will generate the abi below and some bytecode:
547+
548+
.. testsetup::
549+
550+
from web3 import Web3
551+
w3 = Web3(Web3.EthereumTesterProvider())
552+
bytecode = "608060405234801561001057600080fd5b506040516106103803806106108339810180604052602081101561003357600080fd5b81019080805164010000000081111561004b57600080fd5b8281019050602081018481111561006157600080fd5b815185602082028301116401000000008211171561007e57600080fd5b5050929190505050806000908051906020019061009c9291906100a3565b505061019c565b82805482825590600052602060002090600f0160109004810192821561015a5791602002820160005b8382111561012a57835183826101000a81548161ffff02191690837e010000000000000000000000000000000000000000000000000000000000009004021790555092602001926002016020816001010492830192600103026100cc565b80156101585782816101000a81549061ffff021916905560020160208160010104928301926001030261012a565b505b509050610167919061016b565b5090565b61019991905b8082111561019557600081816101000a81549061ffff021916905550600101610171565b5090565b90565b610465806101ab6000396000f3fe608060405260043610610051576000357c0100000000000000000000000000000000000000000000000000000000900480633b3230ee14610056578063d7c8a410146100e7578063dfe3136814610153575b600080fd5b34801561006257600080fd5b5061008f6004803603602081101561007957600080fd5b8101908080359060200190929190505050610218565b60405180827dffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff19167dffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff1916815260200191505060405180910390f35b3480156100f357600080fd5b506100fc61026c565b6040518080602001828103825283818151815260200191508051906020019060200280838360005b8381101561013f578082015181840152602081019050610124565b505050509050019250505060405180910390f35b34801561015f57600080fd5b506102166004803603602081101561017657600080fd5b810190808035906020019064010000000081111561019357600080fd5b8201836020820111156101a557600080fd5b803590602001918460208302840111640100000000831117156101c757600080fd5b919080806020026020016040519081016040528093929190818152602001838360200280828437600081840152601f19601f820116905080830192505050505050509192919290505050610326565b005b60008181548110151561022757fe5b9060005260206000209060109182820401919006600202915054906101000a90047e010000000000000000000000000000000000000000000000000000000000000281565b6060600080548060200260200160405190810160405280929190818152602001828054801561031c57602002820191906000526020600020906000905b82829054906101000a90047e01000000000000000000000000000000000000000000000000000000000000027dffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff1916815260200190600201906020826001010492830192600103820291508084116102a95790505b5050505050905090565b806000908051906020019061033c929190610340565b5050565b82805482825590600052602060002090600f016010900481019282156103f75791602002820160005b838211156103c757835183826101000a81548161ffff02191690837e01000000000000000000000000000000000000000000000000000000000000900402179055509260200192600201602081600101049283019260010302610369565b80156103f55782816101000a81549061ffff02191690556002016020816001010492830192600103026103c7565b505b5090506104049190610408565b5090565b61043691905b8082111561043257600081816101000a81549061ffff02191690555060010161040e565b5090565b9056fea165627a7a72305820a8f9f1f4815c1eedfb8df31298a5cd13b198895de878871328b5d96296b69b4e0029"
553+
554+
.. code-block::
555+
556+
>>> # pragma solidity >=0.4.22 <0.6.0;
557+
...
558+
... # contract ArraysContract {
559+
... # bytes2[] public bytes2Value;
560+
561+
... # constructor(bytes2[] memory _bytes2Value) public {
562+
... # bytes2Value = _bytes2Value;
563+
... # }
564+
565+
... # function setBytes2Value(bytes2[] memory _bytes2Value) public {
566+
... # bytes2Value = _bytes2Value;
567+
... # }
568+
569+
... # function getBytes2Value() public view returns (bytes2[] memory) {
570+
... # return bytes2Value;
571+
... # }
572+
... # }
573+
574+
.. doctest::
575+
576+
>>> abi = '''
577+
... [
578+
... {
579+
... "constant": true,
580+
... "inputs": [
581+
... {
582+
... "name": "",
583+
... "type": "uint256"
584+
... }
585+
... ],
586+
... "name": "bytes2Value",
587+
... "outputs": [
588+
... {
589+
... "name": "",
590+
... "type": "bytes2"
591+
... }
592+
... ],
593+
... "payable": false,
594+
... "stateMutability": "view",
595+
... "type": "function"
596+
... },
597+
... {
598+
... "constant": true,
599+
... "inputs": [],
600+
... "name": "getBytes2Value",
601+
... "outputs": [
602+
... {
603+
... "name": "",
604+
... "type": "bytes2[]"
605+
... }
606+
... ],
607+
... "payable": false,
608+
... "stateMutability": "view",
609+
... "type": "function"
610+
... },
611+
... {
612+
... "constant": false,
613+
... "inputs": [
614+
... {
615+
... "name": "_bytes2Value",
616+
... "type": "bytes2[]"
617+
... }
618+
... ],
619+
... "name": "setBytes2Value",
620+
... "outputs": [],
621+
... "payable": false,
622+
... "stateMutability": "nonpayable",
623+
... "type": "function"
624+
... },
625+
... {
626+
... "inputs": [
627+
... {
628+
... "name": "_bytes2Value",
629+
... "type": "bytes2[]"
630+
... }
631+
... ],
632+
... "payable": false,
633+
... "stateMutability": "nonpayable",
634+
... "type": "constructor"
635+
... }
636+
... ]
637+
... '''.strip()
638+
>>> # bytecode = "6080..."
639+
640+
>>> ArraysContract = w3.eth.contract(abi=abi, bytecode=bytecode)
641+
642+
>>> tx_hash = ArraysContract.constructor([b'b']).transact()
643+
>>> tx_receipt = w3.eth.waitForTransactionReceipt(tx_hash)
644+
645+
>>> array_contract = w3.eth.contract(
646+
... address=tx_receipt.contractAddress,
647+
... abi=abi
648+
... )
649+
650+
>>> array_contract.functions.getBytes2Value().call()
651+
[b'b\x00']
652+
>>> array_contract.functions.setBytes2Value([b'a']).transact()
653+
HexBytes('0x39bc9a0bf5b8ec8e8115ccb20bf02f5570351a20a8fd774da91353f38535bec1')
654+
>>> array_contract.functions.getBytes2Value().call()
655+
[b'a\x00']
656+
>>> w3.enable_strict_bytes_type_checking()
657+
>>> array_contract.functions.setBytes2Value([b'a']).transact()
658+
Traceback (most recent call last):
659+
...
660+
ValidationError:
661+
Could not identify the intended function with name `setBytes2Value`
662+
494663
Contract Functions
495664
------------------
496665

docs/examples.rst

Lines changed: 18 additions & 18 deletions
Original file line numberDiff line numberDiff line change
@@ -202,19 +202,19 @@ Given the following solidity source file stored at ``contract.sol``.
202202
.. code-block:: javascript
203203
204204
contract StoreVar {
205-
205+
206206
uint8 public _myVar;
207207
event MyEvent(uint indexed _var);
208-
208+
209209
function setVar(uint8 _var) public {
210210
_myVar = _var;
211211
MyEvent(_var);
212212
}
213-
213+
214214
function getVar() public view returns (uint8) {
215215
return _myVar;
216216
}
217-
217+
218218
}
219219
220220
The following example demonstrates a few things:
@@ -229,45 +229,45 @@ The following example demonstrates a few things:
229229
import sys
230230
import time
231231
import pprint
232-
232+
233233
from web3.providers.eth_tester import EthereumTesterProvider
234234
from web3 import Web3
235235
from solc import compile_source
236-
236+
237237
238238
def compile_source_file(file_path):
239239
with open(file_path, 'r') as f:
240240
source = f.read()
241-
241+
242242
return compile_source(source)
243-
244-
243+
244+
245245
def deploy_contract(w3, contract_interface):
246246
tx_hash = w3.eth.contract(
247247
abi=contract_interface['abi'],
248248
bytecode=contract_interface['bin']).deploy()
249-
249+
250250
address = w3.eth.getTransactionReceipt(tx_hash)['contractAddress']
251251
return address
252-
253-
252+
253+
254254
w3 = Web3(EthereumTesterProvider())
255-
255+
256256
contract_source_path = 'contract.sol'
257257
compiled_sol = compile_source_file('contract.sol')
258-
258+
259259
contract_id, contract_interface = compiled_sol.popitem()
260-
260+
261261
address = deploy_contract(w3, contract_interface)
262262
print("Deployed {0} to: {1}\n".format(contract_id, address))
263-
263+
264264
store_var_contract = w3.eth.contract(
265265
address=address,
266266
abi=contract_interface['abi'])
267-
267+
268268
gas_estimate = store_var_contract.functions.setVar(255).estimateGas()
269269
print("Gas estimate to transact with setVar: {0}\n".format(gas_estimate))
270-
270+
271271
if gas_estimate < 100000:
272272
print("Sending transaction to setVar(255)\n")
273273
tx_hash = store_var_contract.functions.setVar(255).transact()

0 commit comments

Comments
 (0)