Skip to content

Instantly share code, notes, and snippets.

@holiman
Last active October 15, 2018 12:52
Show Gist options
  • Star 1 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save holiman/0399d4962b40a1df5d493b2cc08fd2f2 to your computer and use it in GitHub Desktop.
Save holiman/0399d4962b40a1df5d493b2cc08fd2f2 to your computer and use it in GitHub Desktop.

This is the trace from geth

#~/go/src/github.com/ethereum/go-ethereum/build/bin/evm --json statetest ropsten_mini.json 
{"pc":0,"op":51,"gas":"0x23ccaa","gasCost":"0x2","memory":"0x","memSize":0,"stack":[],"depth":1,"refund":0,"opName":"CALLER","error":""}
{"pc":1,"op":48,"gas":"0x23cca8","gasCost":"0x2","memory":"0x","memSize":0,"stack":["0xa94f5374fce5edbc8e2a8697c15331677e6ebf0b"],"depth":1,"refund":0,"opName":"ADDRESS","error":""}
{"pc":2,"op":20,"gas":"0x23cca6","gasCost":"0x3","memory":"0x","memSize":0,"stack":["0xa94f5374fce5edbc8e2a8697c15331677e6ebf0b","0xe12d6474ac4964b9f23812bf3375c1fe637ad3b6"],"depth":1,"refund":0,"opName":"EQ","error":""}
{"pc":3,"op":96,"gas":"0x23cca3","gasCost":"0x3","memory":"0x","memSize":0,"stack":["0x0"],"depth":1,"refund":0,"opName":"PUSH1","error":""}
{"pc":5,"op":87,"gas":"0x23cca0","gasCost":"0xa","memory":"0x","memSize":0,"stack":["0x0","0x15"],"depth":1,"refund":0,"opName":"JUMPI","error":""}
{"pc":6,"op":96,"gas":"0x23cc96","gasCost":"0x3","memory":"0x","memSize":0,"stack":[],"depth":1,"refund":0,"opName":"PUSH1","error":""}
{"pc":8,"op":96,"gas":"0x23cc93","gasCost":"0x3","memory":"0x","memSize":0,"stack":["0x0"],"depth":1,"refund":0,"opName":"PUSH1","error":""}
{"pc":10,"op":85,"gas":"0x23cc90","gasCost":"0x1388","memory":"0x","memSize":0,"stack":["0x0","0x1"],"depth":1,"refund":15000,"opName":"SSTORE","error":""}
{"pc":11,"op":96,"gas":"0x23b908","gasCost":"0x3","memory":"0x","memSize":0,"stack":[],"depth":1,"refund":15000,"opName":"PUSH1","error":""}
{"pc":13,"op":128,"gas":"0x23b905","gasCost":"0x3","memory":"0x","memSize":0,"stack":["0x0"],"depth":1,"refund":15000,"opName":"DUP1","error":""}
{"pc":14,"op":128,"gas":"0x23b902","gasCost":"0x3","memory":"0x","memSize":0,"stack":["0x0","0x0"],"depth":1,"refund":15000,"opName":"DUP1","error":""}
{"pc":15,"op":128,"gas":"0x23b8ff","gasCost":"0x3","memory":"0x","memSize":0,"stack":["0x0","0x0","0x0"],"depth":1,"refund":15000,"opName":"DUP1","error":""}
{"pc":16,"op":128,"gas":"0x23b8fc","gasCost":"0x3","memory":"0x","memSize":0,"stack":["0x0","0x0","0x0","0x0"],"depth":1,"refund":15000,"opName":"DUP1","error":""}
{"pc":17,"op":48,"gas":"0x23b8f9","gasCost":"0x2","memory":"0x","memSize":0,"stack":["0x0","0x0","0x0","0x0","0x0"],"depth":1,"refund":15000,"opName":"ADDRESS","error":""}
{"pc":18,"op":90,"gas":"0x23b8f7","gasCost":"0x2","memory":"0x","memSize":0,"stack":["0x0","0x0","0x0","0x0","0x0","0xe12d6474ac4964b9f23812bf3375c1fe637ad3b6"],"depth":1,"refund":15000,"opName":"GAS","error":""}
{"pc":19,"op":241,"gas":"0x23b8f5","gasCost":"0x232a1d","memory":"0x","memSize":0,"stack":["0x0","0x0","0x0","0x0","0x0","0xe12d6474ac4964b9f23812bf3375c1fe637ad3b6","0x23b8f5"],"depth":1,"refund":15000,"opName":"CALL","error":""}
{"pc":0,"op":51,"gas":"0x232761","gasCost":"0x2","memory":"0x","memSize":0,"stack":[],"depth":2,"refund":15000,"opName":"CALLER","error":""}
{"pc":1,"op":48,"gas":"0x23275f","gasCost":"0x2","memory":"0x","memSize":0,"stack":["0xe12d6474ac4964b9f23812bf3375c1fe637ad3b6"],"depth":2,"refund":15000,"opName":"ADDRESS","error":""}
{"pc":2,"op":20,"gas":"0x23275d","gasCost":"0x3","memory":"0x","memSize":0,"stack":["0xe12d6474ac4964b9f23812bf3375c1fe637ad3b6","0xe12d6474ac4964b9f23812bf3375c1fe637ad3b6"],"depth":2,"refund":15000,"opName":"EQ","error":""}
{"pc":3,"op":96,"gas":"0x23275a","gasCost":"0x3","memory":"0x","memSize":0,"stack":["0x1"],"depth":2,"refund":15000,"opName":"PUSH1","error":""}
{"pc":5,"op":87,"gas":"0x232757","gasCost":"0xa","memory":"0x","memSize":0,"stack":["0x1","0x15"],"depth":2,"refund":15000,"opName":"JUMPI","error":""}
{"pc":21,"op":91,"gas":"0x23274d","gasCost":"0x1","memory":"0x","memSize":0,"stack":[],"depth":2,"refund":15000,"opName":"JUMPDEST","error":""}
{"pc":22,"op":96,"gas":"0x23274c","gasCost":"0x3","memory":"0x","memSize":0,"stack":[],"depth":2,"refund":15000,"opName":"PUSH1","error":""}
{"pc":24,"op":96,"gas":"0x232749","gasCost":"0x3","memory":"0x","memSize":0,"stack":["0x3"],"depth":2,"refund":15000,"opName":"PUSH1","error":""}
{"pc":26,"op":85,"gas":"0x232746","gasCost":"0xc8","memory":"0x","memSize":0,"stack":["0x3","0x1"],"depth":2,"refund":0,"opName":"SSTORE","error":""}
{"pc":27,"op":0,"gas":"0x23267e","gasCost":"0x0","memory":"0x","memSize":0,"stack":[],"depth":2,"refund":0,"opName":"STOP","error":""}
{"pc":20,"op":0,"gas":"0x23b556","gasCost":"0x0","memory":"0x","memSize":0,"stack":["0x1"],"depth":1,"refund":0,"opName":"STOP","error":""}
{"output":"","gasUsed":"0x1754","time":819024}
{"stateRoot": "41cf9857a9d18ec5bb6599b269ce5259a97b360f85d379a232942c385b237b62"}
[
  {
    "name": "SstoreCallToSelfSubRefundBelowZero",
    "pass": true,
    "fork": "Constantinople"
  }
]
"""
This program generats a piece of bytecode which
1. Assumes that slot 1 has non-zero value of '2'
2. Overwrites slot 1 with '0'
3. Calls itself
3.1 Overwrites slot '1' with '3'
3.2 stop
4. stop
The step in 3.1 should decrease the refund counter wiht 15k
"""
#!/usr/bin/env python
import json
import tempfile, os
from evmlab import compiler as c
from evmlab import vm
from evmlab import genesis
def generateCall():
def sstore(k, v):
p.push(v).push(k).op(c.SSTORE)
label = 21
p = c.Program()
# Check if we're calling ourself:
p.op(c.CALLER) #0
p.op(c.ADDRESS)#1
p.op(c.EQ) #2
# Yes, we are, go to 3
p.push(label)
p.op(c.JUMPI)
# No, this is first call
sstore(1,0) # Set slot 1 to 0
# Do the call
p.push(0) # outsize
p.op(c.DUP1) # out
p.op(c.DUP1) # insize
p.op(c.DUP1) # instart
p.op(c.DUP1) # value
p.op(c.ADDRESS) # address
p.op(c.GAS) # gas
p.op(c.CALL) #
p.op(c.STOP) #
#This is 3.1
p.op(c.JUMPDEST) # posotion 21
# Set slot
sstore(1,3)
p.op(c.STOP)
return p.bytecode()
def main():
print("0x%s" % generateCall())
if __name__ == '__main__':
main()
{
"SstoreCallToSelfSubRefundBelowZero": {
"_info": {
"comment": "Test where accnt has slot 1 value of '2', is cleared, then calls itself and overwrites with '3', causing a refund-deduction in second call context",
"filledwith": "manaually filled by @holiman",
"lllcversion": "none",
"source": "none",
"sourceHash": "none"
},
"env": {
"currentCoinbase": "0x2adc25665018aa1fe0e6bc666dac8fc2697ff9ba",
"currentDifficulty": "0x20000",
"currentGasLimit": "0x1000000000",
"currentNumber": "0x01",
"currentTimestamp": "0x03e8",
"previousHash": "0x5e20a0453cecd065ea59c37ac63e079ee08998b6045136a8ce6635c7912ec0b6"
},
"post": {
"Constantinople": [
{
"hash": "0x41cf9857a9d18ec5bb6599b269ce5259a97b360f85d379a232942c385b237b62",
"indexes": {
"data": 0,
"gas": 0,
"value": 0
},
"logs": "0x1dcc4de8dec75d7aab85b567b6ccd41ad312451b948a7413f0a142fd40d49347"
}
]
},
"pre": {
"0xe12d6474ac4964b9f23812bf3375c1fe637ad3b6": {
"balance": "0x00",
"code": "0x3330146015576000600155600080808080305af1005b600360015500",
"nonce": "0x00",
"storage": {
"0x01": "0x0000000000000000000000000000000000000000000000000000000000000002"
}
},
"0xa94f5374fce5edbc8e2a8697c15331677e6ebf0b": {
"balance": "0xffffffffffffffff",
"code": "",
"nonce": "0x00",
"storage": {}
}
},
"transaction": {
"data": [
"0x"
],
"gasLimit": [
"0x241eb2"
],
"gasPrice": "0x01",
"nonce": "0x00",
"secretKey": "0x45a915e4d060149eb4365960e6a7a45f334393093061116b197e3240065ff2d8",
"to": "0xe12d6474ac4964b9f23812bf3375c1fe637ad3b6",
"value": [
"0x00"
]
}
}
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment