'I am prepared permit EIP712, but tx "Reverted", function selector 'Reverted 0x08c379a
I'm trying to send a permit for a transaction, but I get a function call mismatch return if I call through the smartcontract token function. If I call via encodeABI and add the same arguments, I don't see the message in the transaction. I use the following code
def build_permit(owner, spender, value, deadline, web3):
data = {
"types": {
"EIP712Domain": [
{"name": "name", "type": "string"},
{"name": "version", "type": "string"},
{"name": "chainId", "type": "uint256"},
{"name": "verifyingContract", "type": "address"},
],
"Permit": [
{"name": "owner", "type": "address"},
{"name": "spender", "type": "address"},
{"name": "value", "type": "uint256"},
{"name": "nonce", "type": "uint256"},
{"name": "deadline", "type": "uint256"},
],
},
"domain": {
"name": "TestToken",
"version": "1",
"chainId": 4,
"verifyingContract": address_token,
},
"primaryType": "Permit",
"message": {
"owner": owner,
"spender": spender,
"value": value,
"nonce": web3.eth.getTransactionCount(my_account.address),
"deadline": deadline,
},
}
return encode_structured_data(data)
def test_permit():
signer = my_account
owner = my_account.address
holder = signer.address
address_token = SC.USDT("RINKEBY")
spender = SC.ROUTER('RINKEBY')
deadline = int(time.time()) + 3600
#print(deadline)
amount = web3.toWei(1, 'ether')
usdt = token_contract(address_token,web3n(RINKEBY))
permit = build_permit(owner, spender, amount, deadline,web3n(RINKEBY))
signed = signer.sign_message(permit)
tx = usdt.functions.permit(holder, spender, 1000000000000000000, int(time.time()) + 3600, signed.v, Web3.toBytes(signed.r), Web3.toBytes(signed.s)).call()
Why does the beginning of the data start with a different function and how do I get the correct signature?
../PycharmProjects/1/venv/lib/python3.9/site-packages/web3/contract.py:957: in call
return call_contract_function(
../PycharmProjects/1/venv/lib/python3.9/site-packages/web3/contract.py:1501: in call_contract_function
return_data = web3.eth.call(
../PycharmProjects/1/venv/lib/python3.9/site-packages/web3/module.py:57: in caller
result = w3.manager.request_blocking(method_str,
../PycharmProjects/1/venv/lib/python3.9/site-packages/web3/manager.py:198: in request_blocking
return self.formatted_response(response,
../PycharmProjects/1/venv/lib/python3.9/site-packages/web3/manager.py:170: in formatted_response
apply_error_formatters(error_formatters, response)
../PycharmProjects/1/venv/lib/python3.9/site-packages/web3/manager.py:70: in apply_error_formatters
formatted_resp = pipe(response, error_formatters)
cytoolz/functoolz.pyx:667: in cytoolz.functoolz.pipe
???
cytoolz/functoolz.pyx:642: in cytoolz.functoolz.c_pipe
???
response = {'error': {'code': 3, 'data': '0x08c379a000000000000000000000000000000000000000000000000000000000000000200000000000000...207369676e61747572650000', 'message': 'execution reverted: ERC20Permit: invalid signature'}, 'id': 1, 'jsonrpc': '2.0'}
def raise_solidity_error_on_revert(response: RPCResponse) -> RPCResponse:
"""
Reverts contain a `data` attribute with the following layout:
"Reverted "
Function selector for Error(string): 08c379a (4 bytes)
Data offset: 32 (32 bytes)
String length (32 bytes)
Reason string (padded, use string length from above to get meaningful part)
See also https://solidity.readthedocs.io/en/v0.6.3/control-structures.html#revert
"""
if not isinstance(response['error'], dict):
raise ValueError('Error expected to be a dict')
data = response['error'].get('data', '')
# Ganache case:
if isinstance(data, dict) and response['error'].get('message'):
raise ContractLogicError(f'execution reverted: {response["error"]["message"]}')
# Parity/OpenEthereum case:
if data.startswith('Reverted '):
# "Reverted", function selector and offset are always the same for revert errors
prefix = 'Reverted 0x08c379a00000000000000000000000000000000000000000000000000000000000000020' # noqa: 501
if not data.startswith(prefix):
raise ContractLogicError('execution reverted')
reason_length = int(data[len(prefix):len(prefix) + 64], 16)
reason = data[len(prefix) + 64:len(prefix) + 64 + reason_length * 2]
raise ContractLogicError(f'execution reverted: {bytes.fromhex(reason).decode("utf8")}')
# Geth case:
if 'message' in response['error'] and response['error'].get('code', '') == 3:
> raise ContractLogicError(response['error']['message'])
E web3.exceptions.ContractLogicError: execution reverted: ERC20Permit: invalid signature
../PycharmProjects/1/venv/lib/python3.9/site-packages/web3/_utils/method_formatters.py:576: ContractLogicError
Sources
This article follows the attribution requirements of Stack Overflow and is licensed under CC BY-SA 3.0.
Source: Stack Overflow
Solution | Source |
---|