diff --git a/state-surgery/Makefile b/state-surgery/Makefile index 06fa82f760238..7f84f6270094d 100644 --- a/state-surgery/Makefile +++ b/state-surgery/Makefile @@ -1,3 +1,7 @@ surgery: go build -o ./surgery ./cmd/main.go -.PHONY: surgery + +test: + go test ./... + +.PHONY: surgery test diff --git a/state-surgery/hardhat/hardhat.go b/state-surgery/hardhat/hardhat.go index 42d37a3255a93..8ae3c24d99fb9 100644 --- a/state-surgery/hardhat/hardhat.go +++ b/state-surgery/hardhat/hardhat.go @@ -8,6 +8,8 @@ import ( "path/filepath" "strings" "sync" + + "github.com/ethereum-optimism/optimism/state-surgery/solc" ) // `Hardhat` encapsulates all of the functionality required to interact @@ -75,11 +77,11 @@ func (h *Hardhat) initDeployments() error { if strings.Contains(path, "solcInputs") { return nil } - - name := filepath.Join(deploymentPath, h.network, path) - if !strings.HasSuffix(name, ".json") { + if !strings.HasSuffix(path, ".json") { return nil } + + name := filepath.Join(deploymentPath, h.network, path) file, err := os.ReadFile(name) if err != nil { return err @@ -247,3 +249,23 @@ func (h *Hardhat) GetBuildInfo(name string) (*BuildInfo, error) { return buildInfos[0], nil } + +// TODO(tynes): handle fully qualified names properly +func (h *Hardhat) GetStorageLayout(name string) (*solc.StorageLayout, error) { + fqn := ParseFullyQualifiedName(name) + + buildInfo, err := h.GetBuildInfo(name) + if err != nil { + return nil, err + } + + for _, source := range buildInfo.Output.Contracts { + for name, contract := range source { + if name == fqn.ContractName { + return &contract.StorageLayout, nil + } + } + } + + return nil, fmt.Errorf("contract not found for %s", fqn.ContractName) +} diff --git a/state-surgery/hardhat/hardhat_test.go b/state-surgery/hardhat/hardhat_test.go index 3987732fc4ab6..5759da5b7d55f 100644 --- a/state-surgery/hardhat/hardhat_test.go +++ b/state-surgery/hardhat/hardhat_test.go @@ -132,6 +132,8 @@ func TestHardhatGetBuildInfo(t *testing.T) { } func TestHardhatGetDeployments(t *testing.T) { + t.Parallel() + hh, err := hardhat.New( "goerli", []string{"testdata/artifacts"}, @@ -143,3 +145,18 @@ func TestHardhatGetDeployments(t *testing.T) { require.Nil(t, err) require.NotNil(t, deployment) } + +func TestHardhatGetStorageLayout(t *testing.T) { + t.Parallel() + + hh, err := hardhat.New( + "goerli", + []string{"testdata/artifacts"}, + []string{"testdata/deployments"}, + ) + require.Nil(t, err) + + storageLayout, err := hh.GetStorageLayout("HelloWorld") + require.Nil(t, err) + require.NotNil(t, storageLayout) +} diff --git a/state-surgery/hardhat/testdata/artifacts/build-info/41b5106372a301360350245ee188494f.json b/state-surgery/hardhat/testdata/artifacts/build-info/41b5106372a301360350245ee188494f.json new file mode 100644 index 0000000000000..9d083c7431e45 --- /dev/null +++ b/state-surgery/hardhat/testdata/artifacts/build-info/41b5106372a301360350245ee188494f.json @@ -0,0 +1,3076 @@ +{ + "id": "41b5106372a301360350245ee188494f", + "_format": "hh-sol-build-info-1", + "solcVersion": "0.8.15", + "solcLongVersion": "0.8.15+commit.e14f2714", + "input": { + "language": "Solidity", + "sources": { + "contracts/HelloWorld.sol": { + "content": "// SPDX-License-Identifier: MIT\npragma solidity 0.8.15;\n\ncontract HelloWorld {\n uint256 public time;\n address public addr;\n bool public boolean;\n mapping(uint256 => address) public addresses;\n\n uint8 public small;\n\n constructor() {\n time = block.timestamp;\n }\n\n function gm() external returns (uint256) {\n uint256 prev = time;\n time = block.timestamp;\n return prev;\n }\n}\n" + } + }, + "settings": { + "optimizer": { + "enabled": true, + "runs": 200 + }, + "metadata": { + "bytecodeHash": "none" + }, + "outputSelection": { + "*": { + "*": [ + "*", + "storageLayout", + "abi", + "evm.bytecode", + "evm.deployedBytecode", + "evm.methodIdentifiers", + "metadata" + ], + "": [ + "ast" + ] + } + } + } + }, + "output": { + "contracts": { + "contracts/HelloWorld.sol": { + "HelloWorld": { + "abi": [ + { + "inputs": [], + "stateMutability": "nonpayable", + "type": "constructor" + }, + { + "inputs": [], + "name": "addr", + "outputs": [ + { + "internalType": "address", + "name": "", + "type": "address" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "name": "addresses", + "outputs": [ + { + "internalType": "address", + "name": "", + "type": "address" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "boolean", + "outputs": [ + { + "internalType": "bool", + "name": "", + "type": "bool" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "gm", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [], + "name": "small", + "outputs": [ + { + "internalType": "uint8", + "name": "", + "type": "uint8" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "time", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "stateMutability": "view", + "type": "function" + } + ], + "devdoc": { + "kind": "dev", + "methods": {}, + "version": 1 + }, + "evm": { + "assembly": " /* \"contracts/HelloWorld.sol\":57:425 contract HelloWorld {... */\n mstore(0x40, 0x80)\n /* \"contracts/HelloWorld.sol\":234:287 constructor() {... */\n callvalue\n dup1\n iszero\n tag_1\n jumpi\n 0x00\n dup1\n revert\ntag_1:\n pop\n /* \"contracts/HelloWorld.sol\":265:280 block.timestamp */\n timestamp\n /* \"contracts/HelloWorld.sol\":258:262 time */\n 0x00\n /* \"contracts/HelloWorld.sol\":258:280 time = block.timestamp */\n sstore\n /* \"contracts/HelloWorld.sol\":57:425 contract HelloWorld {... */\n dataSize(sub_0)\n dup1\n dataOffset(sub_0)\n 0x00\n codecopy\n 0x00\n return\nstop\n\nsub_0: assembly {\n /* \"contracts/HelloWorld.sol\":57:425 contract HelloWorld {... */\n mstore(0x40, 0x80)\n callvalue\n dup1\n iszero\n tag_1\n jumpi\n 0x00\n dup1\n revert\n tag_1:\n pop\n jumpi(tag_2, lt(calldatasize, 0x04))\n shr(0xe0, calldataload(0x00))\n dup1\n 0x16ada547\n eq\n tag_3\n jumpi\n dup1\n 0x6cf3c25e\n eq\n tag_4\n jumpi\n dup1\n 0x767800de\n eq\n tag_5\n jumpi\n dup1\n 0xc0129d43\n eq\n tag_6\n jumpi\n dup1\n 0xc5b57bdb\n eq\n tag_7\n jumpi\n dup1\n 0xedf26d9b\n eq\n tag_8\n jumpi\n tag_2:\n 0x00\n dup1\n revert\n /* \"contracts/HelloWorld.sol\":83:102 uint256 public time */\n tag_3:\n tag_9\n sload(0x00)\n dup2\n jump\n tag_9:\n mload(0x40)\n /* \"#utility.yul\":160:185 */\n swap1\n dup2\n mstore\n /* \"#utility.yul\":148:150 */\n 0x20\n /* \"#utility.yul\":133:151 */\n add\n /* \"contracts/HelloWorld.sol\":83:102 uint256 public time */\n tag_11:\n mload(0x40)\n dup1\n swap2\n sub\n swap1\n return\n /* \"contracts/HelloWorld.sol\":209:227 uint8 public small */\n tag_4:\n sload(0x03)\n tag_13\n swap1\n 0xff\n and\n dup2\n jump\n tag_13:\n mload(0x40)\n /* \"#utility.yul\":368:372 */\n 0xff\n /* \"#utility.yul\":356:373 */\n swap1\n swap2\n and\n /* \"#utility.yul\":338:374 */\n dup2\n mstore\n /* \"#utility.yul\":326:328 */\n 0x20\n /* \"#utility.yul\":311:329 */\n add\n /* \"contracts/HelloWorld.sol\":209:227 uint8 public small */\n tag_11\n /* \"#utility.yul\":196:380 */\n jump\n /* \"contracts/HelloWorld.sol\":108:127 address public addr */\n tag_5:\n sload(0x01)\n tag_17\n swap1\n sub(shl(0xa0, 0x01), 0x01)\n and\n dup2\n jump\n tag_17:\n mload(0x40)\n sub(shl(0xa0, 0x01), 0x01)\n /* \"#utility.yul\":549:581 */\n swap1\n swap2\n and\n /* \"#utility.yul\":531:582 */\n dup2\n mstore\n /* \"#utility.yul\":519:521 */\n 0x20\n /* \"#utility.yul\":504:522 */\n add\n /* \"contracts/HelloWorld.sol\":108:127 address public addr */\n tag_11\n /* \"#utility.yul\":385:588 */\n jump\n /* \"contracts/HelloWorld.sol\":293:423 function gm() external returns (uint256) {... */\n tag_6:\n /* \"contracts/HelloWorld.sol\":325:332 uint256 */\n 0x00\n /* \"contracts/HelloWorld.sol\":359:363 time */\n dup1\n sload\n /* \"contracts/HelloWorld.sol\":380:395 block.timestamp */\n timestamp\n /* \"contracts/HelloWorld.sol\":373:395 time = block.timestamp */\n swap1\n swap2\n sstore\n /* \"contracts/HelloWorld.sol\":293:423 function gm() external returns (uint256) {... */\n jump(tag_9)\n /* \"contracts/HelloWorld.sol\":133:152 bool public boolean */\n tag_7:\n sload(0x01)\n tag_24\n swap1\n shl(0xa0, 0x01)\n swap1\n div\n 0xff\n and\n dup2\n jump\n tag_24:\n mload(0x40)\n /* \"#utility.yul\":758:772 */\n swap1\n iszero\n /* \"#utility.yul\":751:773 */\n iszero\n /* \"#utility.yul\":733:774 */\n dup2\n mstore\n /* \"#utility.yul\":721:723 */\n 0x20\n /* \"#utility.yul\":706:724 */\n add\n /* \"contracts/HelloWorld.sol\":133:152 bool public boolean */\n tag_11\n /* \"#utility.yul\":593:780 */\n jump\n /* \"contracts/HelloWorld.sol\":158:202 mapping(uint256 => address) public addresses */\n tag_8:\n tag_17\n tag_29\n calldatasize\n 0x04\n tag_30\n jump\t// in\n tag_29:\n mstore(0x20, 0x02)\n 0x00\n swap1\n dup2\n mstore\n 0x40\n swap1\n keccak256\n sload\n sub(shl(0xa0, 0x01), 0x01)\n and\n dup2\n jump\n /* \"#utility.yul\":785:965 */\n tag_30:\n /* \"#utility.yul\":844:850 */\n 0x00\n /* \"#utility.yul\":897:899 */\n 0x20\n /* \"#utility.yul\":885:894 */\n dup3\n /* \"#utility.yul\":876:883 */\n dup5\n /* \"#utility.yul\":872:895 */\n sub\n /* \"#utility.yul\":868:900 */\n slt\n /* \"#utility.yul\":865:917 */\n iszero\n tag_40\n jumpi\n /* \"#utility.yul\":913:914 */\n 0x00\n /* \"#utility.yul\":910:911 */\n dup1\n /* \"#utility.yul\":903:915 */\n revert\n /* \"#utility.yul\":865:917 */\n tag_40:\n pop\n /* \"#utility.yul\":936:959 */\n calldataload\n swap2\n /* \"#utility.yul\":785:965 */\n swap1\n pop\n jump\t// out\n\n auxdata: 0xa164736f6c634300080f000a\n}\n", + "bytecode": { + "functionDebugData": { + "@_22": { + "entryPoint": null, + "id": 22, + "parameterSlots": 0, + "returnSlots": 0 + } + }, + "generatedSources": [], + "linkReferences": {}, + "object": "608060405234801561001057600080fd5b504260005561014d806100246000396000f3fe608060405234801561001057600080fd5b50600436106100625760003560e01c806316ada547146100675780636cf3c25e14610083578063767800de146100a2578063c0129d43146100cd578063c5b57bdb146100da578063edf26d9b146100fe575b600080fd5b61007060005481565b6040519081526020015b60405180910390f35b6003546100909060ff1681565b60405160ff909116815260200161007a565b6001546100b5906001600160a01b031681565b6040516001600160a01b03909116815260200161007a565b6000805442909155610070565b6001546100ee90600160a01b900460ff1681565b604051901515815260200161007a565b6100b561010c366004610127565b6002602052600090815260409020546001600160a01b031681565b60006020828403121561013957600080fd5b503591905056fea164736f6c634300080f000a", + "opcodes": "PUSH1 0x80 PUSH1 0x40 MSTORE CALLVALUE DUP1 ISZERO PUSH2 0x10 JUMPI PUSH1 0x0 DUP1 REVERT JUMPDEST POP TIMESTAMP PUSH1 0x0 SSTORE PUSH2 0x14D DUP1 PUSH2 0x24 PUSH1 0x0 CODECOPY PUSH1 0x0 RETURN INVALID PUSH1 0x80 PUSH1 0x40 MSTORE CALLVALUE DUP1 ISZERO PUSH2 0x10 JUMPI PUSH1 0x0 DUP1 REVERT JUMPDEST POP PUSH1 0x4 CALLDATASIZE LT PUSH2 0x62 JUMPI PUSH1 0x0 CALLDATALOAD PUSH1 0xE0 SHR DUP1 PUSH4 0x16ADA547 EQ PUSH2 0x67 JUMPI DUP1 PUSH4 0x6CF3C25E EQ PUSH2 0x83 JUMPI DUP1 PUSH4 0x767800DE EQ PUSH2 0xA2 JUMPI DUP1 PUSH4 0xC0129D43 EQ PUSH2 0xCD JUMPI DUP1 PUSH4 0xC5B57BDB EQ PUSH2 0xDA JUMPI DUP1 PUSH4 0xEDF26D9B EQ PUSH2 0xFE JUMPI JUMPDEST PUSH1 0x0 DUP1 REVERT JUMPDEST PUSH2 0x70 PUSH1 0x0 SLOAD DUP2 JUMP JUMPDEST PUSH1 0x40 MLOAD SWAP1 DUP2 MSTORE PUSH1 0x20 ADD JUMPDEST PUSH1 0x40 MLOAD DUP1 SWAP2 SUB SWAP1 RETURN JUMPDEST PUSH1 0x3 SLOAD PUSH2 0x90 SWAP1 PUSH1 0xFF AND DUP2 JUMP JUMPDEST PUSH1 0x40 MLOAD PUSH1 0xFF SWAP1 SWAP2 AND DUP2 MSTORE PUSH1 0x20 ADD PUSH2 0x7A JUMP JUMPDEST PUSH1 0x1 SLOAD PUSH2 0xB5 SWAP1 PUSH1 0x1 PUSH1 0x1 PUSH1 0xA0 SHL SUB AND DUP2 JUMP JUMPDEST PUSH1 0x40 MLOAD PUSH1 0x1 PUSH1 0x1 PUSH1 0xA0 SHL SUB SWAP1 SWAP2 AND DUP2 MSTORE PUSH1 0x20 ADD PUSH2 0x7A JUMP JUMPDEST PUSH1 0x0 DUP1 SLOAD TIMESTAMP SWAP1 SWAP2 SSTORE PUSH2 0x70 JUMP JUMPDEST PUSH1 0x1 SLOAD PUSH2 0xEE SWAP1 PUSH1 0x1 PUSH1 0xA0 SHL SWAP1 DIV PUSH1 0xFF AND DUP2 JUMP JUMPDEST PUSH1 0x40 MLOAD SWAP1 ISZERO ISZERO DUP2 MSTORE PUSH1 0x20 ADD PUSH2 0x7A JUMP JUMPDEST PUSH2 0xB5 PUSH2 0x10C CALLDATASIZE PUSH1 0x4 PUSH2 0x127 JUMP JUMPDEST PUSH1 0x2 PUSH1 0x20 MSTORE PUSH1 0x0 SWAP1 DUP2 MSTORE PUSH1 0x40 SWAP1 KECCAK256 SLOAD PUSH1 0x1 PUSH1 0x1 PUSH1 0xA0 SHL SUB AND DUP2 JUMP JUMPDEST PUSH1 0x0 PUSH1 0x20 DUP3 DUP5 SUB SLT ISZERO PUSH2 0x139 JUMPI PUSH1 0x0 DUP1 REVERT JUMPDEST POP CALLDATALOAD SWAP2 SWAP1 POP JUMP INVALID LOG1 PUSH5 0x736F6C6343 STOP ADDMOD 0xF STOP EXP ", + "sourceMap": "57:368:0:-:0;;;234:53;;;;;;;;;-1:-1:-1;265:15:0;258:4;:22;57:368;;;;;;" + }, + "deployedBytecode": { + "functionDebugData": { + "@addr_5": { + "entryPoint": null, + "id": 5, + "parameterSlots": 0, + "returnSlots": 0 + }, + "@addresses_11": { + "entryPoint": null, + "id": 11, + "parameterSlots": 0, + "returnSlots": 0 + }, + "@boolean_7": { + "entryPoint": null, + "id": 7, + "parameterSlots": 0, + "returnSlots": 0 + }, + "@gm_39": { + "entryPoint": null, + "id": 39, + "parameterSlots": 0, + "returnSlots": 1 + }, + "@small_13": { + "entryPoint": null, + "id": 13, + "parameterSlots": 0, + "returnSlots": 0 + }, + "@time_3": { + "entryPoint": null, + "id": 3, + "parameterSlots": 0, + "returnSlots": 0 + }, + "abi_decode_tuple_t_uint256": { + "entryPoint": 295, + "id": null, + "parameterSlots": 2, + "returnSlots": 1 + }, + "abi_encode_tuple_t_address__to_t_address__fromStack_reversed": { + "entryPoint": null, + "id": null, + "parameterSlots": 2, + "returnSlots": 1 + }, + "abi_encode_tuple_t_bool__to_t_bool__fromStack_reversed": { + "entryPoint": null, + "id": null, + "parameterSlots": 2, + "returnSlots": 1 + }, + "abi_encode_tuple_t_uint256__to_t_uint256__fromStack_reversed": { + "entryPoint": null, + "id": null, + "parameterSlots": 2, + "returnSlots": 1 + }, + "abi_encode_tuple_t_uint8__to_t_uint8__fromStack_reversed": { + "entryPoint": null, + "id": null, + "parameterSlots": 2, + "returnSlots": 1 + } + }, + "generatedSources": [ + { + "ast": { + "nodeType": "YulBlock", + "src": "0:967:1", + "statements": [ + { + "nodeType": "YulBlock", + "src": "6:3:1", + "statements": [] + }, + { + "body": { + "nodeType": "YulBlock", + "src": "115:76:1", + "statements": [ + { + "nodeType": "YulAssignment", + "src": "125:26:1", + "value": { + "arguments": [ + { + "name": "headStart", + "nodeType": "YulIdentifier", + "src": "137:9:1" + }, + { + "kind": "number", + "nodeType": "YulLiteral", + "src": "148:2:1", + "type": "", + "value": "32" + } + ], + "functionName": { + "name": "add", + "nodeType": "YulIdentifier", + "src": "133:3:1" + }, + "nodeType": "YulFunctionCall", + "src": "133:18:1" + }, + "variableNames": [ + { + "name": "tail", + "nodeType": "YulIdentifier", + "src": "125:4:1" + } + ] + }, + { + "expression": { + "arguments": [ + { + "name": "headStart", + "nodeType": "YulIdentifier", + "src": "167:9:1" + }, + { + "name": "value0", + "nodeType": "YulIdentifier", + "src": "178:6:1" + } + ], + "functionName": { + "name": "mstore", + "nodeType": "YulIdentifier", + "src": "160:6:1" + }, + "nodeType": "YulFunctionCall", + "src": "160:25:1" + }, + "nodeType": "YulExpressionStatement", + "src": "160:25:1" + } + ] + }, + "name": "abi_encode_tuple_t_uint256__to_t_uint256__fromStack_reversed", + "nodeType": "YulFunctionDefinition", + "parameters": [ + { + "name": "headStart", + "nodeType": "YulTypedName", + "src": "84:9:1", + "type": "" + }, + { + "name": "value0", + "nodeType": "YulTypedName", + "src": "95:6:1", + "type": "" + } + ], + "returnVariables": [ + { + "name": "tail", + "nodeType": "YulTypedName", + "src": "106:4:1", + "type": "" + } + ], + "src": "14:177:1" + }, + { + "body": { + "nodeType": "YulBlock", + "src": "293:87:1", + "statements": [ + { + "nodeType": "YulAssignment", + "src": "303:26:1", + "value": { + "arguments": [ + { + "name": "headStart", + "nodeType": "YulIdentifier", + "src": "315:9:1" + }, + { + "kind": "number", + "nodeType": "YulLiteral", + "src": "326:2:1", + "type": "", + "value": "32" + } + ], + "functionName": { + "name": "add", + "nodeType": "YulIdentifier", + "src": "311:3:1" + }, + "nodeType": "YulFunctionCall", + "src": "311:18:1" + }, + "variableNames": [ + { + "name": "tail", + "nodeType": "YulIdentifier", + "src": "303:4:1" + } + ] + }, + { + "expression": { + "arguments": [ + { + "name": "headStart", + "nodeType": "YulIdentifier", + "src": "345:9:1" + }, + { + "arguments": [ + { + "name": "value0", + "nodeType": "YulIdentifier", + "src": "360:6:1" + }, + { + "kind": "number", + "nodeType": "YulLiteral", + "src": "368:4:1", + "type": "", + "value": "0xff" + } + ], + "functionName": { + "name": "and", + "nodeType": "YulIdentifier", + "src": "356:3:1" + }, + "nodeType": "YulFunctionCall", + "src": "356:17:1" + } + ], + "functionName": { + "name": "mstore", + "nodeType": "YulIdentifier", + "src": "338:6:1" + }, + "nodeType": "YulFunctionCall", + "src": "338:36:1" + }, + "nodeType": "YulExpressionStatement", + "src": "338:36:1" + } + ] + }, + "name": "abi_encode_tuple_t_uint8__to_t_uint8__fromStack_reversed", + "nodeType": "YulFunctionDefinition", + "parameters": [ + { + "name": "headStart", + "nodeType": "YulTypedName", + "src": "262:9:1", + "type": "" + }, + { + "name": "value0", + "nodeType": "YulTypedName", + "src": "273:6:1", + "type": "" + } + ], + "returnVariables": [ + { + "name": "tail", + "nodeType": "YulTypedName", + "src": "284:4:1", + "type": "" + } + ], + "src": "196:184:1" + }, + { + "body": { + "nodeType": "YulBlock", + "src": "486:102:1", + "statements": [ + { + "nodeType": "YulAssignment", + "src": "496:26:1", + "value": { + "arguments": [ + { + "name": "headStart", + "nodeType": "YulIdentifier", + "src": "508:9:1" + }, + { + "kind": "number", + "nodeType": "YulLiteral", + "src": "519:2:1", + "type": "", + "value": "32" + } + ], + "functionName": { + "name": "add", + "nodeType": "YulIdentifier", + "src": "504:3:1" + }, + "nodeType": "YulFunctionCall", + "src": "504:18:1" + }, + "variableNames": [ + { + "name": "tail", + "nodeType": "YulIdentifier", + "src": "496:4:1" + } + ] + }, + { + "expression": { + "arguments": [ + { + "name": "headStart", + "nodeType": "YulIdentifier", + "src": "538:9:1" + }, + { + "arguments": [ + { + "name": "value0", + "nodeType": "YulIdentifier", + "src": "553:6:1" + }, + { + "arguments": [ + { + "arguments": [ + { + "kind": "number", + "nodeType": "YulLiteral", + "src": "569:3:1", + "type": "", + "value": "160" + }, + { + "kind": "number", + "nodeType": "YulLiteral", + "src": "574:1:1", + "type": "", + "value": "1" + } + ], + "functionName": { + "name": "shl", + "nodeType": "YulIdentifier", + "src": "565:3:1" + }, + "nodeType": "YulFunctionCall", + "src": "565:11:1" + }, + { + "kind": "number", + "nodeType": "YulLiteral", + "src": "578:1:1", + "type": "", + "value": "1" + } + ], + "functionName": { + "name": "sub", + "nodeType": "YulIdentifier", + "src": "561:3:1" + }, + "nodeType": "YulFunctionCall", + "src": "561:19:1" + } + ], + "functionName": { + "name": "and", + "nodeType": "YulIdentifier", + "src": "549:3:1" + }, + "nodeType": "YulFunctionCall", + "src": "549:32:1" + } + ], + "functionName": { + "name": "mstore", + "nodeType": "YulIdentifier", + "src": "531:6:1" + }, + "nodeType": "YulFunctionCall", + "src": "531:51:1" + }, + "nodeType": "YulExpressionStatement", + "src": "531:51:1" + } + ] + }, + "name": "abi_encode_tuple_t_address__to_t_address__fromStack_reversed", + "nodeType": "YulFunctionDefinition", + "parameters": [ + { + "name": "headStart", + "nodeType": "YulTypedName", + "src": "455:9:1", + "type": "" + }, + { + "name": "value0", + "nodeType": "YulTypedName", + "src": "466:6:1", + "type": "" + } + ], + "returnVariables": [ + { + "name": "tail", + "nodeType": "YulTypedName", + "src": "477:4:1", + "type": "" + } + ], + "src": "385:203:1" + }, + { + "body": { + "nodeType": "YulBlock", + "src": "688:92:1", + "statements": [ + { + "nodeType": "YulAssignment", + "src": "698:26:1", + "value": { + "arguments": [ + { + "name": "headStart", + "nodeType": "YulIdentifier", + "src": "710:9:1" + }, + { + "kind": "number", + "nodeType": "YulLiteral", + "src": "721:2:1", + "type": "", + "value": "32" + } + ], + "functionName": { + "name": "add", + "nodeType": "YulIdentifier", + "src": "706:3:1" + }, + "nodeType": "YulFunctionCall", + "src": "706:18:1" + }, + "variableNames": [ + { + "name": "tail", + "nodeType": "YulIdentifier", + "src": "698:4:1" + } + ] + }, + { + "expression": { + "arguments": [ + { + "name": "headStart", + "nodeType": "YulIdentifier", + "src": "740:9:1" + }, + { + "arguments": [ + { + "arguments": [ + { + "name": "value0", + "nodeType": "YulIdentifier", + "src": "765:6:1" + } + ], + "functionName": { + "name": "iszero", + "nodeType": "YulIdentifier", + "src": "758:6:1" + }, + "nodeType": "YulFunctionCall", + "src": "758:14:1" + } + ], + "functionName": { + "name": "iszero", + "nodeType": "YulIdentifier", + "src": "751:6:1" + }, + "nodeType": "YulFunctionCall", + "src": "751:22:1" + } + ], + "functionName": { + "name": "mstore", + "nodeType": "YulIdentifier", + "src": "733:6:1" + }, + "nodeType": "YulFunctionCall", + "src": "733:41:1" + }, + "nodeType": "YulExpressionStatement", + "src": "733:41:1" + } + ] + }, + "name": "abi_encode_tuple_t_bool__to_t_bool__fromStack_reversed", + "nodeType": "YulFunctionDefinition", + "parameters": [ + { + "name": "headStart", + "nodeType": "YulTypedName", + "src": "657:9:1", + "type": "" + }, + { + "name": "value0", + "nodeType": "YulTypedName", + "src": "668:6:1", + "type": "" + } + ], + "returnVariables": [ + { + "name": "tail", + "nodeType": "YulTypedName", + "src": "679:4:1", + "type": "" + } + ], + "src": "593:187:1" + }, + { + "body": { + "nodeType": "YulBlock", + "src": "855:110:1", + "statements": [ + { + "body": { + "nodeType": "YulBlock", + "src": "901:16:1", + "statements": [ + { + "expression": { + "arguments": [ + { + "kind": "number", + "nodeType": "YulLiteral", + "src": "910:1:1", + "type": "", + "value": "0" + }, + { + "kind": "number", + "nodeType": "YulLiteral", + "src": "913:1:1", + "type": "", + "value": "0" + } + ], + "functionName": { + "name": "revert", + "nodeType": "YulIdentifier", + "src": "903:6:1" + }, + "nodeType": "YulFunctionCall", + "src": "903:12:1" + }, + "nodeType": "YulExpressionStatement", + "src": "903:12:1" + } + ] + }, + "condition": { + "arguments": [ + { + "arguments": [ + { + "name": "dataEnd", + "nodeType": "YulIdentifier", + "src": "876:7:1" + }, + { + "name": "headStart", + "nodeType": "YulIdentifier", + "src": "885:9:1" + } + ], + "functionName": { + "name": "sub", + "nodeType": "YulIdentifier", + "src": "872:3:1" + }, + "nodeType": "YulFunctionCall", + "src": "872:23:1" + }, + { + "kind": "number", + "nodeType": "YulLiteral", + "src": "897:2:1", + "type": "", + "value": "32" + } + ], + "functionName": { + "name": "slt", + "nodeType": "YulIdentifier", + "src": "868:3:1" + }, + "nodeType": "YulFunctionCall", + "src": "868:32:1" + }, + "nodeType": "YulIf", + "src": "865:52:1" + }, + { + "nodeType": "YulAssignment", + "src": "926:33:1", + "value": { + "arguments": [ + { + "name": "headStart", + "nodeType": "YulIdentifier", + "src": "949:9:1" + } + ], + "functionName": { + "name": "calldataload", + "nodeType": "YulIdentifier", + "src": "936:12:1" + }, + "nodeType": "YulFunctionCall", + "src": "936:23:1" + }, + "variableNames": [ + { + "name": "value0", + "nodeType": "YulIdentifier", + "src": "926:6:1" + } + ] + } + ] + }, + "name": "abi_decode_tuple_t_uint256", + "nodeType": "YulFunctionDefinition", + "parameters": [ + { + "name": "headStart", + "nodeType": "YulTypedName", + "src": "821:9:1", + "type": "" + }, + { + "name": "dataEnd", + "nodeType": "YulTypedName", + "src": "832:7:1", + "type": "" + } + ], + "returnVariables": [ + { + "name": "value0", + "nodeType": "YulTypedName", + "src": "844:6:1", + "type": "" + } + ], + "src": "785:180:1" + } + ] + }, + "contents": "{\n { }\n function abi_encode_tuple_t_uint256__to_t_uint256__fromStack_reversed(headStart, value0) -> tail\n {\n tail := add(headStart, 32)\n mstore(headStart, value0)\n }\n function abi_encode_tuple_t_uint8__to_t_uint8__fromStack_reversed(headStart, value0) -> tail\n {\n tail := add(headStart, 32)\n mstore(headStart, and(value0, 0xff))\n }\n function abi_encode_tuple_t_address__to_t_address__fromStack_reversed(headStart, value0) -> tail\n {\n tail := add(headStart, 32)\n mstore(headStart, and(value0, sub(shl(160, 1), 1)))\n }\n function abi_encode_tuple_t_bool__to_t_bool__fromStack_reversed(headStart, value0) -> tail\n {\n tail := add(headStart, 32)\n mstore(headStart, iszero(iszero(value0)))\n }\n function abi_decode_tuple_t_uint256(headStart, dataEnd) -> value0\n {\n if slt(sub(dataEnd, headStart), 32) { revert(0, 0) }\n value0 := calldataload(headStart)\n }\n}", + "id": 1, + "language": "Yul", + "name": "#utility.yul" + } + ], + "immutableReferences": {}, + "linkReferences": {}, + "object": "608060405234801561001057600080fd5b50600436106100625760003560e01c806316ada547146100675780636cf3c25e14610083578063767800de146100a2578063c0129d43146100cd578063c5b57bdb146100da578063edf26d9b146100fe575b600080fd5b61007060005481565b6040519081526020015b60405180910390f35b6003546100909060ff1681565b60405160ff909116815260200161007a565b6001546100b5906001600160a01b031681565b6040516001600160a01b03909116815260200161007a565b6000805442909155610070565b6001546100ee90600160a01b900460ff1681565b604051901515815260200161007a565b6100b561010c366004610127565b6002602052600090815260409020546001600160a01b031681565b60006020828403121561013957600080fd5b503591905056fea164736f6c634300080f000a", + "opcodes": "PUSH1 0x80 PUSH1 0x40 MSTORE CALLVALUE DUP1 ISZERO PUSH2 0x10 JUMPI PUSH1 0x0 DUP1 REVERT JUMPDEST POP PUSH1 0x4 CALLDATASIZE LT PUSH2 0x62 JUMPI PUSH1 0x0 CALLDATALOAD PUSH1 0xE0 SHR DUP1 PUSH4 0x16ADA547 EQ PUSH2 0x67 JUMPI DUP1 PUSH4 0x6CF3C25E EQ PUSH2 0x83 JUMPI DUP1 PUSH4 0x767800DE EQ PUSH2 0xA2 JUMPI DUP1 PUSH4 0xC0129D43 EQ PUSH2 0xCD JUMPI DUP1 PUSH4 0xC5B57BDB EQ PUSH2 0xDA JUMPI DUP1 PUSH4 0xEDF26D9B EQ PUSH2 0xFE JUMPI JUMPDEST PUSH1 0x0 DUP1 REVERT JUMPDEST PUSH2 0x70 PUSH1 0x0 SLOAD DUP2 JUMP JUMPDEST PUSH1 0x40 MLOAD SWAP1 DUP2 MSTORE PUSH1 0x20 ADD JUMPDEST PUSH1 0x40 MLOAD DUP1 SWAP2 SUB SWAP1 RETURN JUMPDEST PUSH1 0x3 SLOAD PUSH2 0x90 SWAP1 PUSH1 0xFF AND DUP2 JUMP JUMPDEST PUSH1 0x40 MLOAD PUSH1 0xFF SWAP1 SWAP2 AND DUP2 MSTORE PUSH1 0x20 ADD PUSH2 0x7A JUMP JUMPDEST PUSH1 0x1 SLOAD PUSH2 0xB5 SWAP1 PUSH1 0x1 PUSH1 0x1 PUSH1 0xA0 SHL SUB AND DUP2 JUMP JUMPDEST PUSH1 0x40 MLOAD PUSH1 0x1 PUSH1 0x1 PUSH1 0xA0 SHL SUB SWAP1 SWAP2 AND DUP2 MSTORE PUSH1 0x20 ADD PUSH2 0x7A JUMP JUMPDEST PUSH1 0x0 DUP1 SLOAD TIMESTAMP SWAP1 SWAP2 SSTORE PUSH2 0x70 JUMP JUMPDEST PUSH1 0x1 SLOAD PUSH2 0xEE SWAP1 PUSH1 0x1 PUSH1 0xA0 SHL SWAP1 DIV PUSH1 0xFF AND DUP2 JUMP JUMPDEST PUSH1 0x40 MLOAD SWAP1 ISZERO ISZERO DUP2 MSTORE PUSH1 0x20 ADD PUSH2 0x7A JUMP JUMPDEST PUSH2 0xB5 PUSH2 0x10C CALLDATASIZE PUSH1 0x4 PUSH2 0x127 JUMP JUMPDEST PUSH1 0x2 PUSH1 0x20 MSTORE PUSH1 0x0 SWAP1 DUP2 MSTORE PUSH1 0x40 SWAP1 KECCAK256 SLOAD PUSH1 0x1 PUSH1 0x1 PUSH1 0xA0 SHL SUB AND DUP2 JUMP JUMPDEST PUSH1 0x0 PUSH1 0x20 DUP3 DUP5 SUB SLT ISZERO PUSH2 0x139 JUMPI PUSH1 0x0 DUP1 REVERT JUMPDEST POP CALLDATALOAD SWAP2 SWAP1 POP JUMP INVALID LOG1 PUSH5 0x736F6C6343 STOP ADDMOD 0xF STOP EXP ", + "sourceMap": "57:368:0:-:0;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;83:19;;;;;;;;;160:25:1;;;148:2;133:18;83:19:0;;;;;;;;209:18;;;;;;;;;;;;368:4:1;356:17;;;338:36;;326:2;311:18;209::0;196:184:1;108:19:0;;;;;-1:-1:-1;;;;;108:19:0;;;;;;-1:-1:-1;;;;;549:32:1;;;531:51;;519:2;504:18;108:19:0;385:203:1;293:130:0;325:7;359:4;;380:15;373:22;;;293:130;;133:19;;;;;-1:-1:-1;;;133:19:0;;;;;;;;;758:14:1;;751:22;733:41;;721:2;706:18;133:19:0;593:187:1;158:44:0;;;;;;:::i;:::-;;;;;;;;;;;;-1:-1:-1;;;;;158:44:0;;;785:180:1;844:6;897:2;885:9;876:7;872:23;868:32;865:52;;;913:1;910;903:12;865:52;-1:-1:-1;936:23:1;;785:180;-1:-1:-1;785:180:1:o" + }, + "gasEstimates": { + "creation": { + "codeDepositCost": "66600", + "executionCost": "22222", + "totalCost": "88822" + }, + "external": { + "addr()": "2359", + "addresses(uint256)": "2565", + "boolean()": "2393", + "gm()": "24436", + "small()": "2313", + "time()": "2262" + } + }, + "legacyAssembly": { + ".code": [ + { + "begin": 57, + "end": 425, + "name": "PUSH", + "source": 0, + "value": "80" + }, + { + "begin": 57, + "end": 425, + "name": "PUSH", + "source": 0, + "value": "40" + }, + { + "begin": 57, + "end": 425, + "name": "MSTORE", + "source": 0 + }, + { + "begin": 234, + "end": 287, + "name": "CALLVALUE", + "source": 0 + }, + { + "begin": 234, + "end": 287, + "name": "DUP1", + "source": 0 + }, + { + "begin": 234, + "end": 287, + "name": "ISZERO", + "source": 0 + }, + { + "begin": 234, + "end": 287, + "name": "PUSH [tag]", + "source": 0, + "value": "1" + }, + { + "begin": 234, + "end": 287, + "name": "JUMPI", + "source": 0 + }, + { + "begin": 234, + "end": 287, + "name": "PUSH", + "source": 0, + "value": "0" + }, + { + "begin": 234, + "end": 287, + "name": "DUP1", + "source": 0 + }, + { + "begin": 234, + "end": 287, + "name": "REVERT", + "source": 0 + }, + { + "begin": 234, + "end": 287, + "name": "tag", + "source": 0, + "value": "1" + }, + { + "begin": 234, + "end": 287, + "name": "JUMPDEST", + "source": 0 + }, + { + "begin": -1, + "end": -1, + "name": "POP", + "source": -1 + }, + { + "begin": 265, + "end": 280, + "name": "TIMESTAMP", + "source": 0 + }, + { + "begin": 258, + "end": 262, + "name": "PUSH", + "source": 0, + "value": "0" + }, + { + "begin": 258, + "end": 280, + "name": "SSTORE", + "source": 0 + }, + { + "begin": 57, + "end": 425, + "name": "PUSH #[$]", + "source": 0, + "value": "0000000000000000000000000000000000000000000000000000000000000000" + }, + { + "begin": 57, + "end": 425, + "name": "DUP1", + "source": 0 + }, + { + "begin": 57, + "end": 425, + "name": "PUSH [$]", + "source": 0, + "value": "0000000000000000000000000000000000000000000000000000000000000000" + }, + { + "begin": 57, + "end": 425, + "name": "PUSH", + "source": 0, + "value": "0" + }, + { + "begin": 57, + "end": 425, + "name": "CODECOPY", + "source": 0 + }, + { + "begin": 57, + "end": 425, + "name": "PUSH", + "source": 0, + "value": "0" + }, + { + "begin": 57, + "end": 425, + "name": "RETURN", + "source": 0 + } + ], + ".data": { + "0": { + ".auxdata": "a164736f6c634300080f000a", + ".code": [ + { + "begin": 57, + "end": 425, + "name": "PUSH", + "source": 0, + "value": "80" + }, + { + "begin": 57, + "end": 425, + "name": "PUSH", + "source": 0, + "value": "40" + }, + { + "begin": 57, + "end": 425, + "name": "MSTORE", + "source": 0 + }, + { + "begin": 57, + "end": 425, + "name": "CALLVALUE", + "source": 0 + }, + { + "begin": 57, + "end": 425, + "name": "DUP1", + "source": 0 + }, + { + "begin": 57, + "end": 425, + "name": "ISZERO", + "source": 0 + }, + { + "begin": 57, + "end": 425, + "name": "PUSH [tag]", + "source": 0, + "value": "1" + }, + { + "begin": 57, + "end": 425, + "name": "JUMPI", + "source": 0 + }, + { + "begin": 57, + "end": 425, + "name": "PUSH", + "source": 0, + "value": "0" + }, + { + "begin": 57, + "end": 425, + "name": "DUP1", + "source": 0 + }, + { + "begin": 57, + "end": 425, + "name": "REVERT", + "source": 0 + }, + { + "begin": 57, + "end": 425, + "name": "tag", + "source": 0, + "value": "1" + }, + { + "begin": 57, + "end": 425, + "name": "JUMPDEST", + "source": 0 + }, + { + "begin": 57, + "end": 425, + "name": "POP", + "source": 0 + }, + { + "begin": 57, + "end": 425, + "name": "PUSH", + "source": 0, + "value": "4" + }, + { + "begin": 57, + "end": 425, + "name": "CALLDATASIZE", + "source": 0 + }, + { + "begin": 57, + "end": 425, + "name": "LT", + "source": 0 + }, + { + "begin": 57, + "end": 425, + "name": "PUSH [tag]", + "source": 0, + "value": "2" + }, + { + "begin": 57, + "end": 425, + "name": "JUMPI", + "source": 0 + }, + { + "begin": 57, + "end": 425, + "name": "PUSH", + "source": 0, + "value": "0" + }, + { + "begin": 57, + "end": 425, + "name": "CALLDATALOAD", + "source": 0 + }, + { + "begin": 57, + "end": 425, + "name": "PUSH", + "source": 0, + "value": "E0" + }, + { + "begin": 57, + "end": 425, + "name": "SHR", + "source": 0 + }, + { + "begin": 57, + "end": 425, + "name": "DUP1", + "source": 0 + }, + { + "begin": 57, + "end": 425, + "name": "PUSH", + "source": 0, + "value": "16ADA547" + }, + { + "begin": 57, + "end": 425, + "name": "EQ", + "source": 0 + }, + { + "begin": 57, + "end": 425, + "name": "PUSH [tag]", + "source": 0, + "value": "3" + }, + { + "begin": 57, + "end": 425, + "name": "JUMPI", + "source": 0 + }, + { + "begin": 57, + "end": 425, + "name": "DUP1", + "source": 0 + }, + { + "begin": 57, + "end": 425, + "name": "PUSH", + "source": 0, + "value": "6CF3C25E" + }, + { + "begin": 57, + "end": 425, + "name": "EQ", + "source": 0 + }, + { + "begin": 57, + "end": 425, + "name": "PUSH [tag]", + "source": 0, + "value": "4" + }, + { + "begin": 57, + "end": 425, + "name": "JUMPI", + "source": 0 + }, + { + "begin": 57, + "end": 425, + "name": "DUP1", + "source": 0 + }, + { + "begin": 57, + "end": 425, + "name": "PUSH", + "source": 0, + "value": "767800DE" + }, + { + "begin": 57, + "end": 425, + "name": "EQ", + "source": 0 + }, + { + "begin": 57, + "end": 425, + "name": "PUSH [tag]", + "source": 0, + "value": "5" + }, + { + "begin": 57, + "end": 425, + "name": "JUMPI", + "source": 0 + }, + { + "begin": 57, + "end": 425, + "name": "DUP1", + "source": 0 + }, + { + "begin": 57, + "end": 425, + "name": "PUSH", + "source": 0, + "value": "C0129D43" + }, + { + "begin": 57, + "end": 425, + "name": "EQ", + "source": 0 + }, + { + "begin": 57, + "end": 425, + "name": "PUSH [tag]", + "source": 0, + "value": "6" + }, + { + "begin": 57, + "end": 425, + "name": "JUMPI", + "source": 0 + }, + { + "begin": 57, + "end": 425, + "name": "DUP1", + "source": 0 + }, + { + "begin": 57, + "end": 425, + "name": "PUSH", + "source": 0, + "value": "C5B57BDB" + }, + { + "begin": 57, + "end": 425, + "name": "EQ", + "source": 0 + }, + { + "begin": 57, + "end": 425, + "name": "PUSH [tag]", + "source": 0, + "value": "7" + }, + { + "begin": 57, + "end": 425, + "name": "JUMPI", + "source": 0 + }, + { + "begin": 57, + "end": 425, + "name": "DUP1", + "source": 0 + }, + { + "begin": 57, + "end": 425, + "name": "PUSH", + "source": 0, + "value": "EDF26D9B" + }, + { + "begin": 57, + "end": 425, + "name": "EQ", + "source": 0 + }, + { + "begin": 57, + "end": 425, + "name": "PUSH [tag]", + "source": 0, + "value": "8" + }, + { + "begin": 57, + "end": 425, + "name": "JUMPI", + "source": 0 + }, + { + "begin": 57, + "end": 425, + "name": "tag", + "source": 0, + "value": "2" + }, + { + "begin": 57, + "end": 425, + "name": "JUMPDEST", + "source": 0 + }, + { + "begin": 57, + "end": 425, + "name": "PUSH", + "source": 0, + "value": "0" + }, + { + "begin": 57, + "end": 425, + "name": "DUP1", + "source": 0 + }, + { + "begin": 57, + "end": 425, + "name": "REVERT", + "source": 0 + }, + { + "begin": 83, + "end": 102, + "name": "tag", + "source": 0, + "value": "3" + }, + { + "begin": 83, + "end": 102, + "name": "JUMPDEST", + "source": 0 + }, + { + "begin": 83, + "end": 102, + "name": "PUSH [tag]", + "source": 0, + "value": "9" + }, + { + "begin": 83, + "end": 102, + "name": "PUSH", + "source": 0, + "value": "0" + }, + { + "begin": 83, + "end": 102, + "name": "SLOAD", + "source": 0 + }, + { + "begin": 83, + "end": 102, + "name": "DUP2", + "source": 0 + }, + { + "begin": 83, + "end": 102, + "name": "JUMP", + "source": 0 + }, + { + "begin": 83, + "end": 102, + "name": "tag", + "source": 0, + "value": "9" + }, + { + "begin": 83, + "end": 102, + "name": "JUMPDEST", + "source": 0 + }, + { + "begin": 83, + "end": 102, + "name": "PUSH", + "source": 0, + "value": "40" + }, + { + "begin": 83, + "end": 102, + "name": "MLOAD", + "source": 0 + }, + { + "begin": 160, + "end": 185, + "name": "SWAP1", + "source": 1 + }, + { + "begin": 160, + "end": 185, + "name": "DUP2", + "source": 1 + }, + { + "begin": 160, + "end": 185, + "name": "MSTORE", + "source": 1 + }, + { + "begin": 148, + "end": 150, + "name": "PUSH", + "source": 1, + "value": "20" + }, + { + "begin": 133, + "end": 151, + "name": "ADD", + "source": 1 + }, + { + "begin": 83, + "end": 102, + "name": "tag", + "source": 0, + "value": "11" + }, + { + "begin": 83, + "end": 102, + "name": "JUMPDEST", + "source": 0 + }, + { + "begin": 83, + "end": 102, + "name": "PUSH", + "source": 0, + "value": "40" + }, + { + "begin": 83, + "end": 102, + "name": "MLOAD", + "source": 0 + }, + { + "begin": 83, + "end": 102, + "name": "DUP1", + "source": 0 + }, + { + "begin": 83, + "end": 102, + "name": "SWAP2", + "source": 0 + }, + { + "begin": 83, + "end": 102, + "name": "SUB", + "source": 0 + }, + { + "begin": 83, + "end": 102, + "name": "SWAP1", + "source": 0 + }, + { + "begin": 83, + "end": 102, + "name": "RETURN", + "source": 0 + }, + { + "begin": 209, + "end": 227, + "name": "tag", + "source": 0, + "value": "4" + }, + { + "begin": 209, + "end": 227, + "name": "JUMPDEST", + "source": 0 + }, + { + "begin": 209, + "end": 227, + "name": "PUSH", + "source": 0, + "value": "3" + }, + { + "begin": 209, + "end": 227, + "name": "SLOAD", + "source": 0 + }, + { + "begin": 209, + "end": 227, + "name": "PUSH [tag]", + "source": 0, + "value": "13" + }, + { + "begin": 209, + "end": 227, + "name": "SWAP1", + "source": 0 + }, + { + "begin": 209, + "end": 227, + "name": "PUSH", + "source": 0, + "value": "FF" + }, + { + "begin": 209, + "end": 227, + "name": "AND", + "source": 0 + }, + { + "begin": 209, + "end": 227, + "name": "DUP2", + "source": 0 + }, + { + "begin": 209, + "end": 227, + "name": "JUMP", + "source": 0 + }, + { + "begin": 209, + "end": 227, + "name": "tag", + "source": 0, + "value": "13" + }, + { + "begin": 209, + "end": 227, + "name": "JUMPDEST", + "source": 0 + }, + { + "begin": 209, + "end": 227, + "name": "PUSH", + "source": 0, + "value": "40" + }, + { + "begin": 209, + "end": 227, + "name": "MLOAD", + "source": 0 + }, + { + "begin": 368, + "end": 372, + "name": "PUSH", + "source": 1, + "value": "FF" + }, + { + "begin": 356, + "end": 373, + "name": "SWAP1", + "source": 1 + }, + { + "begin": 356, + "end": 373, + "name": "SWAP2", + "source": 1 + }, + { + "begin": 356, + "end": 373, + "name": "AND", + "source": 1 + }, + { + "begin": 338, + "end": 374, + "name": "DUP2", + "source": 1 + }, + { + "begin": 338, + "end": 374, + "name": "MSTORE", + "source": 1 + }, + { + "begin": 326, + "end": 328, + "name": "PUSH", + "source": 1, + "value": "20" + }, + { + "begin": 311, + "end": 329, + "name": "ADD", + "source": 1 + }, + { + "begin": 209, + "end": 227, + "name": "PUSH [tag]", + "source": 0, + "value": "11" + }, + { + "begin": 196, + "end": 380, + "name": "JUMP", + "source": 1 + }, + { + "begin": 108, + "end": 127, + "name": "tag", + "source": 0, + "value": "5" + }, + { + "begin": 108, + "end": 127, + "name": "JUMPDEST", + "source": 0 + }, + { + "begin": 108, + "end": 127, + "name": "PUSH", + "source": 0, + "value": "1" + }, + { + "begin": 108, + "end": 127, + "name": "SLOAD", + "source": 0 + }, + { + "begin": 108, + "end": 127, + "name": "PUSH [tag]", + "source": 0, + "value": "17" + }, + { + "begin": 108, + "end": 127, + "name": "SWAP1", + "source": 0 + }, + { + "begin": -1, + "end": -1, + "name": "PUSH", + "source": -1, + "value": "1" + }, + { + "begin": -1, + "end": -1, + "name": "PUSH", + "source": -1, + "value": "1" + }, + { + "begin": -1, + "end": -1, + "name": "PUSH", + "source": -1, + "value": "A0" + }, + { + "begin": -1, + "end": -1, + "name": "SHL", + "source": -1 + }, + { + "begin": -1, + "end": -1, + "name": "SUB", + "source": -1 + }, + { + "begin": 108, + "end": 127, + "name": "AND", + "source": 0 + }, + { + "begin": 108, + "end": 127, + "name": "DUP2", + "source": 0 + }, + { + "begin": 108, + "end": 127, + "name": "JUMP", + "source": 0 + }, + { + "begin": 108, + "end": 127, + "name": "tag", + "source": 0, + "value": "17" + }, + { + "begin": 108, + "end": 127, + "name": "JUMPDEST", + "source": 0 + }, + { + "begin": 108, + "end": 127, + "name": "PUSH", + "source": 0, + "value": "40" + }, + { + "begin": 108, + "end": 127, + "name": "MLOAD", + "source": 0 + }, + { + "begin": -1, + "end": -1, + "name": "PUSH", + "source": -1, + "value": "1" + }, + { + "begin": -1, + "end": -1, + "name": "PUSH", + "source": -1, + "value": "1" + }, + { + "begin": -1, + "end": -1, + "name": "PUSH", + "source": -1, + "value": "A0" + }, + { + "begin": -1, + "end": -1, + "name": "SHL", + "source": -1 + }, + { + "begin": -1, + "end": -1, + "name": "SUB", + "source": -1 + }, + { + "begin": 549, + "end": 581, + "name": "SWAP1", + "source": 1 + }, + { + "begin": 549, + "end": 581, + "name": "SWAP2", + "source": 1 + }, + { + "begin": 549, + "end": 581, + "name": "AND", + "source": 1 + }, + { + "begin": 531, + "end": 582, + "name": "DUP2", + "source": 1 + }, + { + "begin": 531, + "end": 582, + "name": "MSTORE", + "source": 1 + }, + { + "begin": 519, + "end": 521, + "name": "PUSH", + "source": 1, + "value": "20" + }, + { + "begin": 504, + "end": 522, + "name": "ADD", + "source": 1 + }, + { + "begin": 108, + "end": 127, + "name": "PUSH [tag]", + "source": 0, + "value": "11" + }, + { + "begin": 385, + "end": 588, + "name": "JUMP", + "source": 1 + }, + { + "begin": 293, + "end": 423, + "name": "tag", + "source": 0, + "value": "6" + }, + { + "begin": 293, + "end": 423, + "name": "JUMPDEST", + "source": 0 + }, + { + "begin": 325, + "end": 332, + "name": "PUSH", + "source": 0, + "value": "0" + }, + { + "begin": 359, + "end": 363, + "name": "DUP1", + "source": 0 + }, + { + "begin": 359, + "end": 363, + "name": "SLOAD", + "source": 0 + }, + { + "begin": 380, + "end": 395, + "name": "TIMESTAMP", + "source": 0 + }, + { + "begin": 373, + "end": 395, + "name": "SWAP1", + "source": 0 + }, + { + "begin": 373, + "end": 395, + "name": "SWAP2", + "source": 0 + }, + { + "begin": 373, + "end": 395, + "name": "SSTORE", + "source": 0 + }, + { + "begin": 293, + "end": 423, + "name": "PUSH [tag]", + "source": 0, + "value": "9" + }, + { + "begin": 293, + "end": 423, + "name": "JUMP", + "source": 0 + }, + { + "begin": 133, + "end": 152, + "name": "tag", + "source": 0, + "value": "7" + }, + { + "begin": 133, + "end": 152, + "name": "JUMPDEST", + "source": 0 + }, + { + "begin": 133, + "end": 152, + "name": "PUSH", + "source": 0, + "value": "1" + }, + { + "begin": 133, + "end": 152, + "name": "SLOAD", + "source": 0 + }, + { + "begin": 133, + "end": 152, + "name": "PUSH [tag]", + "source": 0, + "value": "24" + }, + { + "begin": 133, + "end": 152, + "name": "SWAP1", + "source": 0 + }, + { + "begin": -1, + "end": -1, + "name": "PUSH", + "source": -1, + "value": "1" + }, + { + "begin": -1, + "end": -1, + "name": "PUSH", + "source": -1, + "value": "A0" + }, + { + "begin": -1, + "end": -1, + "name": "SHL", + "source": -1 + }, + { + "begin": 133, + "end": 152, + "name": "SWAP1", + "source": 0 + }, + { + "begin": 133, + "end": 152, + "name": "DIV", + "source": 0 + }, + { + "begin": 133, + "end": 152, + "name": "PUSH", + "source": 0, + "value": "FF" + }, + { + "begin": 133, + "end": 152, + "name": "AND", + "source": 0 + }, + { + "begin": 133, + "end": 152, + "name": "DUP2", + "source": 0 + }, + { + "begin": 133, + "end": 152, + "name": "JUMP", + "source": 0 + }, + { + "begin": 133, + "end": 152, + "name": "tag", + "source": 0, + "value": "24" + }, + { + "begin": 133, + "end": 152, + "name": "JUMPDEST", + "source": 0 + }, + { + "begin": 133, + "end": 152, + "name": "PUSH", + "source": 0, + "value": "40" + }, + { + "begin": 133, + "end": 152, + "name": "MLOAD", + "source": 0 + }, + { + "begin": 758, + "end": 772, + "name": "SWAP1", + "source": 1 + }, + { + "begin": 758, + "end": 772, + "name": "ISZERO", + "source": 1 + }, + { + "begin": 751, + "end": 773, + "name": "ISZERO", + "source": 1 + }, + { + "begin": 733, + "end": 774, + "name": "DUP2", + "source": 1 + }, + { + "begin": 733, + "end": 774, + "name": "MSTORE", + "source": 1 + }, + { + "begin": 721, + "end": 723, + "name": "PUSH", + "source": 1, + "value": "20" + }, + { + "begin": 706, + "end": 724, + "name": "ADD", + "source": 1 + }, + { + "begin": 133, + "end": 152, + "name": "PUSH [tag]", + "source": 0, + "value": "11" + }, + { + "begin": 593, + "end": 780, + "name": "JUMP", + "source": 1 + }, + { + "begin": 158, + "end": 202, + "name": "tag", + "source": 0, + "value": "8" + }, + { + "begin": 158, + "end": 202, + "name": "JUMPDEST", + "source": 0 + }, + { + "begin": 158, + "end": 202, + "name": "PUSH [tag]", + "source": 0, + "value": "17" + }, + { + "begin": 158, + "end": 202, + "name": "PUSH [tag]", + "source": 0, + "value": "29" + }, + { + "begin": 158, + "end": 202, + "name": "CALLDATASIZE", + "source": 0 + }, + { + "begin": 158, + "end": 202, + "name": "PUSH", + "source": 0, + "value": "4" + }, + { + "begin": 158, + "end": 202, + "name": "PUSH [tag]", + "source": 0, + "value": "30" + }, + { + "begin": 158, + "end": 202, + "jumpType": "[in]", + "name": "JUMP", + "source": 0 + }, + { + "begin": 158, + "end": 202, + "name": "tag", + "source": 0, + "value": "29" + }, + { + "begin": 158, + "end": 202, + "name": "JUMPDEST", + "source": 0 + }, + { + "begin": 158, + "end": 202, + "name": "PUSH", + "source": 0, + "value": "2" + }, + { + "begin": 158, + "end": 202, + "name": "PUSH", + "source": 0, + "value": "20" + }, + { + "begin": 158, + "end": 202, + "name": "MSTORE", + "source": 0 + }, + { + "begin": 158, + "end": 202, + "name": "PUSH", + "source": 0, + "value": "0" + }, + { + "begin": 158, + "end": 202, + "name": "SWAP1", + "source": 0 + }, + { + "begin": 158, + "end": 202, + "name": "DUP2", + "source": 0 + }, + { + "begin": 158, + "end": 202, + "name": "MSTORE", + "source": 0 + }, + { + "begin": 158, + "end": 202, + "name": "PUSH", + "source": 0, + "value": "40" + }, + { + "begin": 158, + "end": 202, + "name": "SWAP1", + "source": 0 + }, + { + "begin": 158, + "end": 202, + "name": "KECCAK256", + "source": 0 + }, + { + "begin": 158, + "end": 202, + "name": "SLOAD", + "source": 0 + }, + { + "begin": -1, + "end": -1, + "name": "PUSH", + "source": -1, + "value": "1" + }, + { + "begin": -1, + "end": -1, + "name": "PUSH", + "source": -1, + "value": "1" + }, + { + "begin": -1, + "end": -1, + "name": "PUSH", + "source": -1, + "value": "A0" + }, + { + "begin": -1, + "end": -1, + "name": "SHL", + "source": -1 + }, + { + "begin": -1, + "end": -1, + "name": "SUB", + "source": -1 + }, + { + "begin": 158, + "end": 202, + "name": "AND", + "source": 0 + }, + { + "begin": 158, + "end": 202, + "name": "DUP2", + "source": 0 + }, + { + "begin": 158, + "end": 202, + "name": "JUMP", + "source": 0 + }, + { + "begin": 785, + "end": 965, + "name": "tag", + "source": 1, + "value": "30" + }, + { + "begin": 785, + "end": 965, + "name": "JUMPDEST", + "source": 1 + }, + { + "begin": 844, + "end": 850, + "name": "PUSH", + "source": 1, + "value": "0" + }, + { + "begin": 897, + "end": 899, + "name": "PUSH", + "source": 1, + "value": "20" + }, + { + "begin": 885, + "end": 894, + "name": "DUP3", + "source": 1 + }, + { + "begin": 876, + "end": 883, + "name": "DUP5", + "source": 1 + }, + { + "begin": 872, + "end": 895, + "name": "SUB", + "source": 1 + }, + { + "begin": 868, + "end": 900, + "name": "SLT", + "source": 1 + }, + { + "begin": 865, + "end": 917, + "name": "ISZERO", + "source": 1 + }, + { + "begin": 865, + "end": 917, + "name": "PUSH [tag]", + "source": 1, + "value": "40" + }, + { + "begin": 865, + "end": 917, + "name": "JUMPI", + "source": 1 + }, + { + "begin": 913, + "end": 914, + "name": "PUSH", + "source": 1, + "value": "0" + }, + { + "begin": 910, + "end": 911, + "name": "DUP1", + "source": 1 + }, + { + "begin": 903, + "end": 915, + "name": "REVERT", + "source": 1 + }, + { + "begin": 865, + "end": 917, + "name": "tag", + "source": 1, + "value": "40" + }, + { + "begin": 865, + "end": 917, + "name": "JUMPDEST", + "source": 1 + }, + { + "begin": -1, + "end": -1, + "name": "POP", + "source": -1 + }, + { + "begin": 936, + "end": 959, + "name": "CALLDATALOAD", + "source": 1 + }, + { + "begin": 936, + "end": 959, + "name": "SWAP2", + "source": 1 + }, + { + "begin": 785, + "end": 965, + "name": "SWAP1", + "source": 1 + }, + { + "begin": -1, + "end": -1, + "name": "POP", + "source": -1 + }, + { + "begin": 785, + "end": 965, + "jumpType": "[out]", + "name": "JUMP", + "source": 1 + } + ] + } + }, + "sourceList": [ + "contracts/HelloWorld.sol", + "#utility.yul" + ] + }, + "methodIdentifiers": { + "addr()": "767800de", + "addresses(uint256)": "edf26d9b", + "boolean()": "c5b57bdb", + "gm()": "c0129d43", + "small()": "6cf3c25e", + "time()": "16ada547" + } + }, + "ewasm": { + "wasm": "" + }, + "metadata": "{\"compiler\":{\"version\":\"0.8.15+commit.e14f2714\"},\"language\":\"Solidity\",\"output\":{\"abi\":[{\"inputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"constructor\"},{\"inputs\":[],\"name\":\"addr\",\"outputs\":[{\"internalType\":\"address\",\"name\":\"\",\"type\":\"address\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"name\":\"addresses\",\"outputs\":[{\"internalType\":\"address\",\"name\":\"\",\"type\":\"address\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"boolean\",\"outputs\":[{\"internalType\":\"bool\",\"name\":\"\",\"type\":\"bool\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"gm\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"small\",\"outputs\":[{\"internalType\":\"uint8\",\"name\":\"\",\"type\":\"uint8\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"time\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"stateMutability\":\"view\",\"type\":\"function\"}],\"devdoc\":{\"kind\":\"dev\",\"methods\":{},\"version\":1},\"userdoc\":{\"kind\":\"user\",\"methods\":{},\"version\":1}},\"settings\":{\"compilationTarget\":{\"contracts/HelloWorld.sol\":\"HelloWorld\"},\"evmVersion\":\"london\",\"libraries\":{},\"metadata\":{\"bytecodeHash\":\"none\"},\"optimizer\":{\"enabled\":true,\"runs\":200},\"remappings\":[]},\"sources\":{\"contracts/HelloWorld.sol\":{\"keccak256\":\"0x0299929b9cb2f54573d11c3d487e615bd508b42deb031fc8810eb5eba1aa88d8\",\"license\":\"MIT\",\"urls\":[\"bzz-raw://85ddc5bb88506abf72d8e6ba7b9d157cfcd9beae0241333f48b76faf13ccdfbc\",\"dweb:/ipfs/QmWUZuDdrkqK4SW3ee9ew2gQRxkkigLydX3pQaEXncJEjZ\"]}},\"version\":1}", + "storageLayout": { + "storage": [ + { + "astId": 3, + "contract": "contracts/HelloWorld.sol:HelloWorld", + "label": "time", + "offset": 0, + "slot": "0", + "type": "t_uint256" + }, + { + "astId": 5, + "contract": "contracts/HelloWorld.sol:HelloWorld", + "label": "addr", + "offset": 0, + "slot": "1", + "type": "t_address" + }, + { + "astId": 7, + "contract": "contracts/HelloWorld.sol:HelloWorld", + "label": "boolean", + "offset": 20, + "slot": "1", + "type": "t_bool" + }, + { + "astId": 11, + "contract": "contracts/HelloWorld.sol:HelloWorld", + "label": "addresses", + "offset": 0, + "slot": "2", + "type": "t_mapping(t_uint256,t_address)" + }, + { + "astId": 13, + "contract": "contracts/HelloWorld.sol:HelloWorld", + "label": "small", + "offset": 0, + "slot": "3", + "type": "t_uint8" + } + ], + "types": { + "t_address": { + "encoding": "inplace", + "label": "address", + "numberOfBytes": "20" + }, + "t_bool": { + "encoding": "inplace", + "label": "bool", + "numberOfBytes": "1" + }, + "t_mapping(t_uint256,t_address)": { + "encoding": "mapping", + "key": "t_uint256", + "label": "mapping(uint256 => address)", + "numberOfBytes": "32", + "value": "t_address" + }, + "t_uint256": { + "encoding": "inplace", + "label": "uint256", + "numberOfBytes": "32" + }, + "t_uint8": { + "encoding": "inplace", + "label": "uint8", + "numberOfBytes": "1" + } + } + }, + "userdoc": { + "kind": "user", + "methods": {}, + "version": 1 + } + } + } + }, + "sources": { + "contracts/HelloWorld.sol": { + "ast": { + "absolutePath": "contracts/HelloWorld.sol", + "exportedSymbols": { + "HelloWorld": [ + 40 + ] + }, + "id": 41, + "license": "MIT", + "nodeType": "SourceUnit", + "nodes": [ + { + "id": 1, + "literals": [ + "solidity", + "0.8", + ".15" + ], + "nodeType": "PragmaDirective", + "src": "32:23:0" + }, + { + "abstract": false, + "baseContracts": [], + "canonicalName": "HelloWorld", + "contractDependencies": [], + "contractKind": "contract", + "fullyImplemented": true, + "id": 40, + "linearizedBaseContracts": [ + 40 + ], + "name": "HelloWorld", + "nameLocation": "66:10:0", + "nodeType": "ContractDefinition", + "nodes": [ + { + "constant": false, + "functionSelector": "16ada547", + "id": 3, + "mutability": "mutable", + "name": "time", + "nameLocation": "98:4:0", + "nodeType": "VariableDeclaration", + "scope": 40, + "src": "83:19:0", + "stateVariable": true, + "storageLocation": "default", + "typeDescriptions": { + "typeIdentifier": "t_uint256", + "typeString": "uint256" + }, + "typeName": { + "id": 2, + "name": "uint256", + "nodeType": "ElementaryTypeName", + "src": "83:7:0", + "typeDescriptions": { + "typeIdentifier": "t_uint256", + "typeString": "uint256" + } + }, + "visibility": "public" + }, + { + "constant": false, + "functionSelector": "767800de", + "id": 5, + "mutability": "mutable", + "name": "addr", + "nameLocation": "123:4:0", + "nodeType": "VariableDeclaration", + "scope": 40, + "src": "108:19:0", + "stateVariable": true, + "storageLocation": "default", + "typeDescriptions": { + "typeIdentifier": "t_address", + "typeString": "address" + }, + "typeName": { + "id": 4, + "name": "address", + "nodeType": "ElementaryTypeName", + "src": "108:7:0", + "stateMutability": "nonpayable", + "typeDescriptions": { + "typeIdentifier": "t_address", + "typeString": "address" + } + }, + "visibility": "public" + }, + { + "constant": false, + "functionSelector": "c5b57bdb", + "id": 7, + "mutability": "mutable", + "name": "boolean", + "nameLocation": "145:7:0", + "nodeType": "VariableDeclaration", + "scope": 40, + "src": "133:19:0", + "stateVariable": true, + "storageLocation": "default", + "typeDescriptions": { + "typeIdentifier": "t_bool", + "typeString": "bool" + }, + "typeName": { + "id": 6, + "name": "bool", + "nodeType": "ElementaryTypeName", + "src": "133:4:0", + "typeDescriptions": { + "typeIdentifier": "t_bool", + "typeString": "bool" + } + }, + "visibility": "public" + }, + { + "constant": false, + "functionSelector": "edf26d9b", + "id": 11, + "mutability": "mutable", + "name": "addresses", + "nameLocation": "193:9:0", + "nodeType": "VariableDeclaration", + "scope": 40, + "src": "158:44:0", + "stateVariable": true, + "storageLocation": "default", + "typeDescriptions": { + "typeIdentifier": "t_mapping$_t_uint256_$_t_address_$", + "typeString": "mapping(uint256 => address)" + }, + "typeName": { + "id": 10, + "keyType": { + "id": 8, + "name": "uint256", + "nodeType": "ElementaryTypeName", + "src": "166:7:0", + "typeDescriptions": { + "typeIdentifier": "t_uint256", + "typeString": "uint256" + } + }, + "nodeType": "Mapping", + "src": "158:27:0", + "typeDescriptions": { + "typeIdentifier": "t_mapping$_t_uint256_$_t_address_$", + "typeString": "mapping(uint256 => address)" + }, + "valueType": { + "id": 9, + "name": "address", + "nodeType": "ElementaryTypeName", + "src": "177:7:0", + "stateMutability": "nonpayable", + "typeDescriptions": { + "typeIdentifier": "t_address", + "typeString": "address" + } + } + }, + "visibility": "public" + }, + { + "constant": false, + "functionSelector": "6cf3c25e", + "id": 13, + "mutability": "mutable", + "name": "small", + "nameLocation": "222:5:0", + "nodeType": "VariableDeclaration", + "scope": 40, + "src": "209:18:0", + "stateVariable": true, + "storageLocation": "default", + "typeDescriptions": { + "typeIdentifier": "t_uint8", + "typeString": "uint8" + }, + "typeName": { + "id": 12, + "name": "uint8", + "nodeType": "ElementaryTypeName", + "src": "209:5:0", + "typeDescriptions": { + "typeIdentifier": "t_uint8", + "typeString": "uint8" + } + }, + "visibility": "public" + }, + { + "body": { + "id": 21, + "nodeType": "Block", + "src": "248:39:0", + "statements": [ + { + "expression": { + "id": 19, + "isConstant": false, + "isLValue": false, + "isPure": false, + "lValueRequested": false, + "leftHandSide": { + "id": 16, + "name": "time", + "nodeType": "Identifier", + "overloadedDeclarations": [], + "referencedDeclaration": 3, + "src": "258:4:0", + "typeDescriptions": { + "typeIdentifier": "t_uint256", + "typeString": "uint256" + } + }, + "nodeType": "Assignment", + "operator": "=", + "rightHandSide": { + "expression": { + "id": 17, + "name": "block", + "nodeType": "Identifier", + "overloadedDeclarations": [], + "referencedDeclaration": -4, + "src": "265:5:0", + "typeDescriptions": { + "typeIdentifier": "t_magic_block", + "typeString": "block" + } + }, + "id": 18, + "isConstant": false, + "isLValue": false, + "isPure": false, + "lValueRequested": false, + "memberName": "timestamp", + "nodeType": "MemberAccess", + "src": "265:15:0", + "typeDescriptions": { + "typeIdentifier": "t_uint256", + "typeString": "uint256" + } + }, + "src": "258:22:0", + "typeDescriptions": { + "typeIdentifier": "t_uint256", + "typeString": "uint256" + } + }, + "id": 20, + "nodeType": "ExpressionStatement", + "src": "258:22:0" + } + ] + }, + "id": 22, + "implemented": true, + "kind": "constructor", + "modifiers": [], + "name": "", + "nameLocation": "-1:-1:-1", + "nodeType": "FunctionDefinition", + "parameters": { + "id": 14, + "nodeType": "ParameterList", + "parameters": [], + "src": "245:2:0" + }, + "returnParameters": { + "id": 15, + "nodeType": "ParameterList", + "parameters": [], + "src": "248:0:0" + }, + "scope": 40, + "src": "234:53:0", + "stateMutability": "nonpayable", + "virtual": false, + "visibility": "public" + }, + { + "body": { + "id": 38, + "nodeType": "Block", + "src": "334:89:0", + "statements": [ + { + "assignments": [ + 28 + ], + "declarations": [ + { + "constant": false, + "id": 28, + "mutability": "mutable", + "name": "prev", + "nameLocation": "352:4:0", + "nodeType": "VariableDeclaration", + "scope": 38, + "src": "344:12:0", + "stateVariable": false, + "storageLocation": "default", + "typeDescriptions": { + "typeIdentifier": "t_uint256", + "typeString": "uint256" + }, + "typeName": { + "id": 27, + "name": "uint256", + "nodeType": "ElementaryTypeName", + "src": "344:7:0", + "typeDescriptions": { + "typeIdentifier": "t_uint256", + "typeString": "uint256" + } + }, + "visibility": "internal" + } + ], + "id": 30, + "initialValue": { + "id": 29, + "name": "time", + "nodeType": "Identifier", + "overloadedDeclarations": [], + "referencedDeclaration": 3, + "src": "359:4:0", + "typeDescriptions": { + "typeIdentifier": "t_uint256", + "typeString": "uint256" + } + }, + "nodeType": "VariableDeclarationStatement", + "src": "344:19:0" + }, + { + "expression": { + "id": 34, + "isConstant": false, + "isLValue": false, + "isPure": false, + "lValueRequested": false, + "leftHandSide": { + "id": 31, + "name": "time", + "nodeType": "Identifier", + "overloadedDeclarations": [], + "referencedDeclaration": 3, + "src": "373:4:0", + "typeDescriptions": { + "typeIdentifier": "t_uint256", + "typeString": "uint256" + } + }, + "nodeType": "Assignment", + "operator": "=", + "rightHandSide": { + "expression": { + "id": 32, + "name": "block", + "nodeType": "Identifier", + "overloadedDeclarations": [], + "referencedDeclaration": -4, + "src": "380:5:0", + "typeDescriptions": { + "typeIdentifier": "t_magic_block", + "typeString": "block" + } + }, + "id": 33, + "isConstant": false, + "isLValue": false, + "isPure": false, + "lValueRequested": false, + "memberName": "timestamp", + "nodeType": "MemberAccess", + "src": "380:15:0", + "typeDescriptions": { + "typeIdentifier": "t_uint256", + "typeString": "uint256" + } + }, + "src": "373:22:0", + "typeDescriptions": { + "typeIdentifier": "t_uint256", + "typeString": "uint256" + } + }, + "id": 35, + "nodeType": "ExpressionStatement", + "src": "373:22:0" + }, + { + "expression": { + "id": 36, + "name": "prev", + "nodeType": "Identifier", + "overloadedDeclarations": [], + "referencedDeclaration": 28, + "src": "412:4:0", + "typeDescriptions": { + "typeIdentifier": "t_uint256", + "typeString": "uint256" + } + }, + "functionReturnParameters": 26, + "id": 37, + "nodeType": "Return", + "src": "405:11:0" + } + ] + }, + "functionSelector": "c0129d43", + "id": 39, + "implemented": true, + "kind": "function", + "modifiers": [], + "name": "gm", + "nameLocation": "302:2:0", + "nodeType": "FunctionDefinition", + "parameters": { + "id": 23, + "nodeType": "ParameterList", + "parameters": [], + "src": "304:2:0" + }, + "returnParameters": { + "id": 26, + "nodeType": "ParameterList", + "parameters": [ + { + "constant": false, + "id": 25, + "mutability": "mutable", + "name": "", + "nameLocation": "-1:-1:-1", + "nodeType": "VariableDeclaration", + "scope": 39, + "src": "325:7:0", + "stateVariable": false, + "storageLocation": "default", + "typeDescriptions": { + "typeIdentifier": "t_uint256", + "typeString": "uint256" + }, + "typeName": { + "id": 24, + "name": "uint256", + "nodeType": "ElementaryTypeName", + "src": "325:7:0", + "typeDescriptions": { + "typeIdentifier": "t_uint256", + "typeString": "uint256" + } + }, + "visibility": "internal" + } + ], + "src": "324:9:0" + }, + "scope": 40, + "src": "293:130:0", + "stateMutability": "nonpayable", + "virtual": false, + "visibility": "external" + } + ], + "scope": 41, + "src": "57:368:0", + "usedErrors": [] + } + ], + "src": "32:394:0" + }, + "id": 0 + } + } + } +} diff --git a/state-surgery/hardhat/testdata/artifacts/build-info/c5729209e616d57e62ada8bf0034436e.json b/state-surgery/hardhat/testdata/artifacts/build-info/c5729209e616d57e62ada8bf0034436e.json deleted file mode 100644 index c0e7760d7a054..0000000000000 --- a/state-surgery/hardhat/testdata/artifacts/build-info/c5729209e616d57e62ada8bf0034436e.json +++ /dev/null @@ -1,717 +0,0 @@ -{ - "id": "c5729209e616d57e62ada8bf0034436e", - "_format": "hh-sol-build-info-1", - "solcVersion": "0.8.15", - "solcLongVersion": "0.8.15+commit.e14f2714", - "input": { - "language": "Solidity", - "sources": { - "contracts/HelloWorld.sol": { - "content": "// SPDX-License-Identifier: MIT\npragma solidity 0.8.15;\n\ncontract HelloWorld {\n uint256 public time;\n\n constructor() {\n time = block.timestamp;\n }\n\n function gm() external returns (uint256) {\n uint256 prev = time;\n time = block.timestamp;\n return prev;\n }\n}\n" - } - }, - "settings": { - "optimizer": { - "enabled": false, - "runs": 200 - }, - "outputSelection": { - "*": { - "*": [ - "abi", - "evm.bytecode", - "evm.deployedBytecode", - "evm.methodIdentifiers", - "metadata" - ], - "": [ - "ast" - ] - } - } - } - }, - "output": { - "contracts": { - "contracts/HelloWorld.sol": { - "HelloWorld": { - "abi": [ - { - "inputs": [], - "stateMutability": "nonpayable", - "type": "constructor" - }, - { - "inputs": [], - "name": "gm", - "outputs": [ - { - "internalType": "uint256", - "name": "", - "type": "uint256" - } - ], - "stateMutability": "nonpayable", - "type": "function" - }, - { - "inputs": [], - "name": "time", - "outputs": [ - { - "internalType": "uint256", - "name": "", - "type": "uint256" - } - ], - "stateMutability": "view", - "type": "function" - } - ], - "evm": { - "bytecode": { - "functionDebugData": { - "@_12": { - "entryPoint": null, - "id": 12, - "parameterSlots": 0, - "returnSlots": 0 - } - }, - "generatedSources": [], - "linkReferences": {}, - "object": "608060405234801561001057600080fd5b504260008190555060ed806100266000396000f3fe6080604052348015600f57600080fd5b506004361060325760003560e01c806316ada547146037578063c0129d43146051575b600080fd5b603d606b565b60405160489190609e565b60405180910390f35b60576071565b60405160629190609e565b60405180910390f35b60005481565b6000806000549050426000819055508091505090565b6000819050919050565b6098816087565b82525050565b600060208201905060b160008301846091565b9291505056fea2646970667358221220880ac624623135a410271b0c719fe0f86b85ff1eb258d2f766c58f2e87907b8864736f6c634300080f0033", - "opcodes": "PUSH1 0x80 PUSH1 0x40 MSTORE CALLVALUE DUP1 ISZERO PUSH2 0x10 JUMPI PUSH1 0x0 DUP1 REVERT JUMPDEST POP TIMESTAMP PUSH1 0x0 DUP2 SWAP1 SSTORE POP PUSH1 0xED DUP1 PUSH2 0x26 PUSH1 0x0 CODECOPY PUSH1 0x0 RETURN INVALID PUSH1 0x80 PUSH1 0x40 MSTORE CALLVALUE DUP1 ISZERO PUSH1 0xF JUMPI PUSH1 0x0 DUP1 REVERT JUMPDEST POP PUSH1 0x4 CALLDATASIZE LT PUSH1 0x32 JUMPI PUSH1 0x0 CALLDATALOAD PUSH1 0xE0 SHR DUP1 PUSH4 0x16ADA547 EQ PUSH1 0x37 JUMPI DUP1 PUSH4 0xC0129D43 EQ PUSH1 0x51 JUMPI JUMPDEST PUSH1 0x0 DUP1 REVERT JUMPDEST PUSH1 0x3D PUSH1 0x6B JUMP JUMPDEST PUSH1 0x40 MLOAD PUSH1 0x48 SWAP2 SWAP1 PUSH1 0x9E JUMP JUMPDEST PUSH1 0x40 MLOAD DUP1 SWAP2 SUB SWAP1 RETURN JUMPDEST PUSH1 0x57 PUSH1 0x71 JUMP JUMPDEST PUSH1 0x40 MLOAD PUSH1 0x62 SWAP2 SWAP1 PUSH1 0x9E JUMP JUMPDEST PUSH1 0x40 MLOAD DUP1 SWAP2 SUB SWAP1 RETURN JUMPDEST PUSH1 0x0 SLOAD DUP2 JUMP JUMPDEST PUSH1 0x0 DUP1 PUSH1 0x0 SLOAD SWAP1 POP TIMESTAMP PUSH1 0x0 DUP2 SWAP1 SSTORE POP DUP1 SWAP2 POP POP SWAP1 JUMP JUMPDEST PUSH1 0x0 DUP2 SWAP1 POP SWAP2 SWAP1 POP JUMP JUMPDEST PUSH1 0x98 DUP2 PUSH1 0x87 JUMP JUMPDEST DUP3 MSTORE POP POP JUMP JUMPDEST PUSH1 0x0 PUSH1 0x20 DUP3 ADD SWAP1 POP PUSH1 0xB1 PUSH1 0x0 DUP4 ADD DUP5 PUSH1 0x91 JUMP JUMPDEST SWAP3 SWAP2 POP POP JUMP INVALID LOG2 PUSH5 0x6970667358 0x22 SLT KECCAK256 DUP9 EXP 0xC6 0x24 PUSH3 0x3135A4 LT 0x27 SHL 0xC PUSH18 0x9FE0F86B85FF1EB258D2F766C58F2E87907B DUP9 PUSH5 0x736F6C6343 STOP ADDMOD 0xF STOP CALLER ", - "sourceMap": "57:243:0:-:0;;;109:53;;;;;;;;;;140:15;133:4;:22;;;;57:243;;;;;;" - }, - "deployedBytecode": { - "functionDebugData": { - "@gm_29": { - "entryPoint": 113, - "id": 29, - "parameterSlots": 0, - "returnSlots": 1 - }, - "@time_3": { - "entryPoint": 107, - "id": 3, - "parameterSlots": 0, - "returnSlots": 0 - }, - "abi_encode_t_uint256_to_t_uint256_fromStack": { - "entryPoint": 145, - "id": null, - "parameterSlots": 2, - "returnSlots": 0 - }, - "abi_encode_tuple_t_uint256__to_t_uint256__fromStack_reversed": { - "entryPoint": 158, - "id": null, - "parameterSlots": 2, - "returnSlots": 1 - }, - "cleanup_t_uint256": { - "entryPoint": 135, - "id": null, - "parameterSlots": 1, - "returnSlots": 1 - } - }, - "generatedSources": [ - { - "ast": { - "nodeType": "YulBlock", - "src": "0:439:1", - "statements": [ - { - "body": { - "nodeType": "YulBlock", - "src": "52:32:1", - "statements": [ - { - "nodeType": "YulAssignment", - "src": "62:16:1", - "value": { - "name": "value", - "nodeType": "YulIdentifier", - "src": "73:5:1" - }, - "variableNames": [ - { - "name": "cleaned", - "nodeType": "YulIdentifier", - "src": "62:7:1" - } - ] - } - ] - }, - "name": "cleanup_t_uint256", - "nodeType": "YulFunctionDefinition", - "parameters": [ - { - "name": "value", - "nodeType": "YulTypedName", - "src": "34:5:1", - "type": "" - } - ], - "returnVariables": [ - { - "name": "cleaned", - "nodeType": "YulTypedName", - "src": "44:7:1", - "type": "" - } - ], - "src": "7:77:1" - }, - { - "body": { - "nodeType": "YulBlock", - "src": "155:53:1", - "statements": [ - { - "expression": { - "arguments": [ - { - "name": "pos", - "nodeType": "YulIdentifier", - "src": "172:3:1" - }, - { - "arguments": [ - { - "name": "value", - "nodeType": "YulIdentifier", - "src": "195:5:1" - } - ], - "functionName": { - "name": "cleanup_t_uint256", - "nodeType": "YulIdentifier", - "src": "177:17:1" - }, - "nodeType": "YulFunctionCall", - "src": "177:24:1" - } - ], - "functionName": { - "name": "mstore", - "nodeType": "YulIdentifier", - "src": "165:6:1" - }, - "nodeType": "YulFunctionCall", - "src": "165:37:1" - }, - "nodeType": "YulExpressionStatement", - "src": "165:37:1" - } - ] - }, - "name": "abi_encode_t_uint256_to_t_uint256_fromStack", - "nodeType": "YulFunctionDefinition", - "parameters": [ - { - "name": "value", - "nodeType": "YulTypedName", - "src": "143:5:1", - "type": "" - }, - { - "name": "pos", - "nodeType": "YulTypedName", - "src": "150:3:1", - "type": "" - } - ], - "src": "90:118:1" - }, - { - "body": { - "nodeType": "YulBlock", - "src": "312:124:1", - "statements": [ - { - "nodeType": "YulAssignment", - "src": "322:26:1", - "value": { - "arguments": [ - { - "name": "headStart", - "nodeType": "YulIdentifier", - "src": "334:9:1" - }, - { - "kind": "number", - "nodeType": "YulLiteral", - "src": "345:2:1", - "type": "", - "value": "32" - } - ], - "functionName": { - "name": "add", - "nodeType": "YulIdentifier", - "src": "330:3:1" - }, - "nodeType": "YulFunctionCall", - "src": "330:18:1" - }, - "variableNames": [ - { - "name": "tail", - "nodeType": "YulIdentifier", - "src": "322:4:1" - } - ] - }, - { - "expression": { - "arguments": [ - { - "name": "value0", - "nodeType": "YulIdentifier", - "src": "402:6:1" - }, - { - "arguments": [ - { - "name": "headStart", - "nodeType": "YulIdentifier", - "src": "415:9:1" - }, - { - "kind": "number", - "nodeType": "YulLiteral", - "src": "426:1:1", - "type": "", - "value": "0" - } - ], - "functionName": { - "name": "add", - "nodeType": "YulIdentifier", - "src": "411:3:1" - }, - "nodeType": "YulFunctionCall", - "src": "411:17:1" - } - ], - "functionName": { - "name": "abi_encode_t_uint256_to_t_uint256_fromStack", - "nodeType": "YulIdentifier", - "src": "358:43:1" - }, - "nodeType": "YulFunctionCall", - "src": "358:71:1" - }, - "nodeType": "YulExpressionStatement", - "src": "358:71:1" - } - ] - }, - "name": "abi_encode_tuple_t_uint256__to_t_uint256__fromStack_reversed", - "nodeType": "YulFunctionDefinition", - "parameters": [ - { - "name": "headStart", - "nodeType": "YulTypedName", - "src": "284:9:1", - "type": "" - }, - { - "name": "value0", - "nodeType": "YulTypedName", - "src": "296:6:1", - "type": "" - } - ], - "returnVariables": [ - { - "name": "tail", - "nodeType": "YulTypedName", - "src": "307:4:1", - "type": "" - } - ], - "src": "214:222:1" - } - ] - }, - "contents": "{\n\n function cleanup_t_uint256(value) -> cleaned {\n cleaned := value\n }\n\n function abi_encode_t_uint256_to_t_uint256_fromStack(value, pos) {\n mstore(pos, cleanup_t_uint256(value))\n }\n\n function abi_encode_tuple_t_uint256__to_t_uint256__fromStack_reversed(headStart , value0) -> tail {\n tail := add(headStart, 32)\n\n abi_encode_t_uint256_to_t_uint256_fromStack(value0, add(headStart, 0))\n\n }\n\n}\n", - "id": 1, - "language": "Yul", - "name": "#utility.yul" - } - ], - "immutableReferences": {}, - "linkReferences": {}, - "object": "6080604052348015600f57600080fd5b506004361060325760003560e01c806316ada547146037578063c0129d43146051575b600080fd5b603d606b565b60405160489190609e565b60405180910390f35b60576071565b60405160629190609e565b60405180910390f35b60005481565b6000806000549050426000819055508091505090565b6000819050919050565b6098816087565b82525050565b600060208201905060b160008301846091565b9291505056fea2646970667358221220880ac624623135a410271b0c719fe0f86b85ff1eb258d2f766c58f2e87907b8864736f6c634300080f0033", - "opcodes": "PUSH1 0x80 PUSH1 0x40 MSTORE CALLVALUE DUP1 ISZERO PUSH1 0xF JUMPI PUSH1 0x0 DUP1 REVERT JUMPDEST POP PUSH1 0x4 CALLDATASIZE LT PUSH1 0x32 JUMPI PUSH1 0x0 CALLDATALOAD PUSH1 0xE0 SHR DUP1 PUSH4 0x16ADA547 EQ PUSH1 0x37 JUMPI DUP1 PUSH4 0xC0129D43 EQ PUSH1 0x51 JUMPI JUMPDEST PUSH1 0x0 DUP1 REVERT JUMPDEST PUSH1 0x3D PUSH1 0x6B JUMP JUMPDEST PUSH1 0x40 MLOAD PUSH1 0x48 SWAP2 SWAP1 PUSH1 0x9E JUMP JUMPDEST PUSH1 0x40 MLOAD DUP1 SWAP2 SUB SWAP1 RETURN JUMPDEST PUSH1 0x57 PUSH1 0x71 JUMP JUMPDEST PUSH1 0x40 MLOAD PUSH1 0x62 SWAP2 SWAP1 PUSH1 0x9E JUMP JUMPDEST PUSH1 0x40 MLOAD DUP1 SWAP2 SUB SWAP1 RETURN JUMPDEST PUSH1 0x0 SLOAD DUP2 JUMP JUMPDEST PUSH1 0x0 DUP1 PUSH1 0x0 SLOAD SWAP1 POP TIMESTAMP PUSH1 0x0 DUP2 SWAP1 SSTORE POP DUP1 SWAP2 POP POP SWAP1 JUMP JUMPDEST PUSH1 0x0 DUP2 SWAP1 POP SWAP2 SWAP1 POP JUMP JUMPDEST PUSH1 0x98 DUP2 PUSH1 0x87 JUMP JUMPDEST DUP3 MSTORE POP POP JUMP JUMPDEST PUSH1 0x0 PUSH1 0x20 DUP3 ADD SWAP1 POP PUSH1 0xB1 PUSH1 0x0 DUP4 ADD DUP5 PUSH1 0x91 JUMP JUMPDEST SWAP3 SWAP2 POP POP JUMP INVALID LOG2 PUSH5 0x6970667358 0x22 SLT KECCAK256 DUP9 EXP 0xC6 0x24 PUSH3 0x3135A4 LT 0x27 SHL 0xC PUSH18 0x9FE0F86B85FF1EB258D2F766C58F2E87907B DUP9 PUSH5 0x736F6C6343 STOP ADDMOD 0xF STOP CALLER ", - "sourceMap": "57:243:0:-:0;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;83:19;;;:::i;:::-;;;;;;;:::i;:::-;;;;;;;;168:130;;;:::i;:::-;;;;;;;:::i;:::-;;;;;;;;83:19;;;;:::o;168:130::-;200:7;219:12;234:4;;219:19;;255:15;248:4;:22;;;;287:4;280:11;;;168:130;:::o;7:77:1:-;44:7;73:5;62:16;;7:77;;;:::o;90:118::-;177:24;195:5;177:24;:::i;:::-;172:3;165:37;90:118;;:::o;214:222::-;307:4;345:2;334:9;330:18;322:26;;358:71;426:1;415:9;411:17;402:6;358:71;:::i;:::-;214:222;;;;:::o" - }, - "methodIdentifiers": { - "gm()": "c0129d43", - "time()": "16ada547" - } - }, - "metadata": "{\"compiler\":{\"version\":\"0.8.15+commit.e14f2714\"},\"language\":\"Solidity\",\"output\":{\"abi\":[{\"inputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"constructor\"},{\"inputs\":[],\"name\":\"gm\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"time\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"stateMutability\":\"view\",\"type\":\"function\"}],\"devdoc\":{\"kind\":\"dev\",\"methods\":{},\"version\":1},\"userdoc\":{\"kind\":\"user\",\"methods\":{},\"version\":1}},\"settings\":{\"compilationTarget\":{\"contracts/HelloWorld.sol\":\"HelloWorld\"},\"evmVersion\":\"london\",\"libraries\":{},\"metadata\":{\"bytecodeHash\":\"ipfs\"},\"optimizer\":{\"enabled\":false,\"runs\":200},\"remappings\":[]},\"sources\":{\"contracts/HelloWorld.sol\":{\"keccak256\":\"0x01a0d5ca485fe13a0d88010439d7fd3c0a7a3528169470b39c695f616b2dd7c5\",\"license\":\"MIT\",\"urls\":[\"bzz-raw://a4c476b397ce1cab9c9d86bb3aabf252aecbcf580ae3ccd982c3c05195ec0e1a\",\"dweb:/ipfs/QmPoVtkyCEVCbGNiFzahpLRNoT28eWejtwmd2aguZiNxAA\"]}},\"version\":1}" - } - } - }, - "sources": { - "contracts/HelloWorld.sol": { - "ast": { - "absolutePath": "contracts/HelloWorld.sol", - "exportedSymbols": { - "HelloWorld": [ - 30 - ] - }, - "id": 31, - "license": "MIT", - "nodeType": "SourceUnit", - "nodes": [ - { - "id": 1, - "literals": [ - "solidity", - "0.8", - ".15" - ], - "nodeType": "PragmaDirective", - "src": "32:23:0" - }, - { - "abstract": false, - "baseContracts": [], - "canonicalName": "HelloWorld", - "contractDependencies": [], - "contractKind": "contract", - "fullyImplemented": true, - "id": 30, - "linearizedBaseContracts": [ - 30 - ], - "name": "HelloWorld", - "nameLocation": "66:10:0", - "nodeType": "ContractDefinition", - "nodes": [ - { - "constant": false, - "functionSelector": "16ada547", - "id": 3, - "mutability": "mutable", - "name": "time", - "nameLocation": "98:4:0", - "nodeType": "VariableDeclaration", - "scope": 30, - "src": "83:19:0", - "stateVariable": true, - "storageLocation": "default", - "typeDescriptions": { - "typeIdentifier": "t_uint256", - "typeString": "uint256" - }, - "typeName": { - "id": 2, - "name": "uint256", - "nodeType": "ElementaryTypeName", - "src": "83:7:0", - "typeDescriptions": { - "typeIdentifier": "t_uint256", - "typeString": "uint256" - } - }, - "visibility": "public" - }, - { - "body": { - "id": 11, - "nodeType": "Block", - "src": "123:39:0", - "statements": [ - { - "expression": { - "id": 9, - "isConstant": false, - "isLValue": false, - "isPure": false, - "lValueRequested": false, - "leftHandSide": { - "id": 6, - "name": "time", - "nodeType": "Identifier", - "overloadedDeclarations": [], - "referencedDeclaration": 3, - "src": "133:4:0", - "typeDescriptions": { - "typeIdentifier": "t_uint256", - "typeString": "uint256" - } - }, - "nodeType": "Assignment", - "operator": "=", - "rightHandSide": { - "expression": { - "id": 7, - "name": "block", - "nodeType": "Identifier", - "overloadedDeclarations": [], - "referencedDeclaration": -4, - "src": "140:5:0", - "typeDescriptions": { - "typeIdentifier": "t_magic_block", - "typeString": "block" - } - }, - "id": 8, - "isConstant": false, - "isLValue": false, - "isPure": false, - "lValueRequested": false, - "memberName": "timestamp", - "nodeType": "MemberAccess", - "src": "140:15:0", - "typeDescriptions": { - "typeIdentifier": "t_uint256", - "typeString": "uint256" - } - }, - "src": "133:22:0", - "typeDescriptions": { - "typeIdentifier": "t_uint256", - "typeString": "uint256" - } - }, - "id": 10, - "nodeType": "ExpressionStatement", - "src": "133:22:0" - } - ] - }, - "id": 12, - "implemented": true, - "kind": "constructor", - "modifiers": [], - "name": "", - "nameLocation": "-1:-1:-1", - "nodeType": "FunctionDefinition", - "parameters": { - "id": 4, - "nodeType": "ParameterList", - "parameters": [], - "src": "120:2:0" - }, - "returnParameters": { - "id": 5, - "nodeType": "ParameterList", - "parameters": [], - "src": "123:0:0" - }, - "scope": 30, - "src": "109:53:0", - "stateMutability": "nonpayable", - "virtual": false, - "visibility": "public" - }, - { - "body": { - "id": 28, - "nodeType": "Block", - "src": "209:89:0", - "statements": [ - { - "assignments": [ - 18 - ], - "declarations": [ - { - "constant": false, - "id": 18, - "mutability": "mutable", - "name": "prev", - "nameLocation": "227:4:0", - "nodeType": "VariableDeclaration", - "scope": 28, - "src": "219:12:0", - "stateVariable": false, - "storageLocation": "default", - "typeDescriptions": { - "typeIdentifier": "t_uint256", - "typeString": "uint256" - }, - "typeName": { - "id": 17, - "name": "uint256", - "nodeType": "ElementaryTypeName", - "src": "219:7:0", - "typeDescriptions": { - "typeIdentifier": "t_uint256", - "typeString": "uint256" - } - }, - "visibility": "internal" - } - ], - "id": 20, - "initialValue": { - "id": 19, - "name": "time", - "nodeType": "Identifier", - "overloadedDeclarations": [], - "referencedDeclaration": 3, - "src": "234:4:0", - "typeDescriptions": { - "typeIdentifier": "t_uint256", - "typeString": "uint256" - } - }, - "nodeType": "VariableDeclarationStatement", - "src": "219:19:0" - }, - { - "expression": { - "id": 24, - "isConstant": false, - "isLValue": false, - "isPure": false, - "lValueRequested": false, - "leftHandSide": { - "id": 21, - "name": "time", - "nodeType": "Identifier", - "overloadedDeclarations": [], - "referencedDeclaration": 3, - "src": "248:4:0", - "typeDescriptions": { - "typeIdentifier": "t_uint256", - "typeString": "uint256" - } - }, - "nodeType": "Assignment", - "operator": "=", - "rightHandSide": { - "expression": { - "id": 22, - "name": "block", - "nodeType": "Identifier", - "overloadedDeclarations": [], - "referencedDeclaration": -4, - "src": "255:5:0", - "typeDescriptions": { - "typeIdentifier": "t_magic_block", - "typeString": "block" - } - }, - "id": 23, - "isConstant": false, - "isLValue": false, - "isPure": false, - "lValueRequested": false, - "memberName": "timestamp", - "nodeType": "MemberAccess", - "src": "255:15:0", - "typeDescriptions": { - "typeIdentifier": "t_uint256", - "typeString": "uint256" - } - }, - "src": "248:22:0", - "typeDescriptions": { - "typeIdentifier": "t_uint256", - "typeString": "uint256" - } - }, - "id": 25, - "nodeType": "ExpressionStatement", - "src": "248:22:0" - }, - { - "expression": { - "id": 26, - "name": "prev", - "nodeType": "Identifier", - "overloadedDeclarations": [], - "referencedDeclaration": 18, - "src": "287:4:0", - "typeDescriptions": { - "typeIdentifier": "t_uint256", - "typeString": "uint256" - } - }, - "functionReturnParameters": 16, - "id": 27, - "nodeType": "Return", - "src": "280:11:0" - } - ] - }, - "functionSelector": "c0129d43", - "id": 29, - "implemented": true, - "kind": "function", - "modifiers": [], - "name": "gm", - "nameLocation": "177:2:0", - "nodeType": "FunctionDefinition", - "parameters": { - "id": 13, - "nodeType": "ParameterList", - "parameters": [], - "src": "179:2:0" - }, - "returnParameters": { - "id": 16, - "nodeType": "ParameterList", - "parameters": [ - { - "constant": false, - "id": 15, - "mutability": "mutable", - "name": "", - "nameLocation": "-1:-1:-1", - "nodeType": "VariableDeclaration", - "scope": 29, - "src": "200:7:0", - "stateVariable": false, - "storageLocation": "default", - "typeDescriptions": { - "typeIdentifier": "t_uint256", - "typeString": "uint256" - }, - "typeName": { - "id": 14, - "name": "uint256", - "nodeType": "ElementaryTypeName", - "src": "200:7:0", - "typeDescriptions": { - "typeIdentifier": "t_uint256", - "typeString": "uint256" - } - }, - "visibility": "internal" - } - ], - "src": "199:9:0" - }, - "scope": 30, - "src": "168:130:0", - "stateMutability": "nonpayable", - "virtual": false, - "visibility": "external" - } - ], - "scope": 31, - "src": "57:243:0", - "usedErrors": [] - } - ], - "src": "32:269:0" - }, - "id": 0 - } - } - } -} diff --git a/state-surgery/hardhat/testdata/artifacts/contracts/HelloWorld.sol/HelloWorld.dbg.json b/state-surgery/hardhat/testdata/artifacts/contracts/HelloWorld.sol/HelloWorld.dbg.json index 79334fd303e84..b657a4331b852 100644 --- a/state-surgery/hardhat/testdata/artifacts/contracts/HelloWorld.sol/HelloWorld.dbg.json +++ b/state-surgery/hardhat/testdata/artifacts/contracts/HelloWorld.sol/HelloWorld.dbg.json @@ -1,4 +1,4 @@ { "_format": "hh-sol-dbg-1", - "buildInfo": "../../build-info/c5729209e616d57e62ada8bf0034436e.json" + "buildInfo": "../../build-info/41b5106372a301360350245ee188494f.json" } diff --git a/state-surgery/hardhat/testdata/artifacts/contracts/HelloWorld.sol/HelloWorld.json b/state-surgery/hardhat/testdata/artifacts/contracts/HelloWorld.sol/HelloWorld.json index 8c8618b047acd..70860803a525d 100644 --- a/state-surgery/hardhat/testdata/artifacts/contracts/HelloWorld.sol/HelloWorld.json +++ b/state-surgery/hardhat/testdata/artifacts/contracts/HelloWorld.sol/HelloWorld.json @@ -8,6 +8,51 @@ "stateMutability": "nonpayable", "type": "constructor" }, + { + "inputs": [], + "name": "addr", + "outputs": [ + { + "internalType": "address", + "name": "", + "type": "address" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "name": "addresses", + "outputs": [ + { + "internalType": "address", + "name": "", + "type": "address" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "boolean", + "outputs": [ + { + "internalType": "bool", + "name": "", + "type": "bool" + } + ], + "stateMutability": "view", + "type": "function" + }, { "inputs": [], "name": "gm", @@ -21,6 +66,19 @@ "stateMutability": "nonpayable", "type": "function" }, + { + "inputs": [], + "name": "small", + "outputs": [ + { + "internalType": "uint8", + "name": "", + "type": "uint8" + } + ], + "stateMutability": "view", + "type": "function" + }, { "inputs": [], "name": "time", @@ -35,8 +93,8 @@ "type": "function" } ], - "bytecode": "0x608060405234801561001057600080fd5b504260008190555060ed806100266000396000f3fe6080604052348015600f57600080fd5b506004361060325760003560e01c806316ada547146037578063c0129d43146051575b600080fd5b603d606b565b60405160489190609e565b60405180910390f35b60576071565b60405160629190609e565b60405180910390f35b60005481565b6000806000549050426000819055508091505090565b6000819050919050565b6098816087565b82525050565b600060208201905060b160008301846091565b9291505056fea2646970667358221220880ac624623135a410271b0c719fe0f86b85ff1eb258d2f766c58f2e87907b8864736f6c634300080f0033", - "deployedBytecode": "0x6080604052348015600f57600080fd5b506004361060325760003560e01c806316ada547146037578063c0129d43146051575b600080fd5b603d606b565b60405160489190609e565b60405180910390f35b60576071565b60405160629190609e565b60405180910390f35b60005481565b6000806000549050426000819055508091505090565b6000819050919050565b6098816087565b82525050565b600060208201905060b160008301846091565b9291505056fea2646970667358221220880ac624623135a410271b0c719fe0f86b85ff1eb258d2f766c58f2e87907b8864736f6c634300080f0033", + "bytecode": "0x608060405234801561001057600080fd5b504260005561014d806100246000396000f3fe608060405234801561001057600080fd5b50600436106100625760003560e01c806316ada547146100675780636cf3c25e14610083578063767800de146100a2578063c0129d43146100cd578063c5b57bdb146100da578063edf26d9b146100fe575b600080fd5b61007060005481565b6040519081526020015b60405180910390f35b6003546100909060ff1681565b60405160ff909116815260200161007a565b6001546100b5906001600160a01b031681565b6040516001600160a01b03909116815260200161007a565b6000805442909155610070565b6001546100ee90600160a01b900460ff1681565b604051901515815260200161007a565b6100b561010c366004610127565b6002602052600090815260409020546001600160a01b031681565b60006020828403121561013957600080fd5b503591905056fea164736f6c634300080f000a", + "deployedBytecode": "0x608060405234801561001057600080fd5b50600436106100625760003560e01c806316ada547146100675780636cf3c25e14610083578063767800de146100a2578063c0129d43146100cd578063c5b57bdb146100da578063edf26d9b146100fe575b600080fd5b61007060005481565b6040519081526020015b60405180910390f35b6003546100909060ff1681565b60405160ff909116815260200161007a565b6001546100b5906001600160a01b031681565b6040516001600160a01b03909116815260200161007a565b6000805442909155610070565b6001546100ee90600160a01b900460ff1681565b604051901515815260200161007a565b6100b561010c366004610127565b6002602052600090815260409020546001600160a01b031681565b60006020828403121561013957600080fd5b503591905056fea164736f6c634300080f000a", "linkReferences": {}, "deployedLinkReferences": {} } diff --git a/state-surgery/hardhat/types.go b/state-surgery/hardhat/types.go index aef55c91de75a..3f0cd94afd46a 100644 --- a/state-surgery/hardhat/types.go +++ b/state-surgery/hardhat/types.go @@ -3,6 +3,7 @@ package hardhat import ( "encoding/json" + "github.com/ethereum-optimism/optimism/state-surgery/solc" "github.com/ethereum/go-ethereum/accounts/abi" "github.com/ethereum/go-ethereum/common" "github.com/ethereum/go-ethereum/common/hexutil" @@ -11,18 +12,18 @@ import ( // Deployment represents a hardhat-deploy artifact file type Deployment struct { Name string - Abi abi.ABI `json:"abi"` - Address common.Address `json:"address"` - Args []any `json:"args"` - Bytecode hexutil.Bytes `json:"bytecode"` - DeployedBytecode hexutil.Bytes `json:"deployedBytecode"` - Devdoc json.RawMessage `json:"devdoc"` - Metadata string `json:"metadata"` - Receipt Receipt `json:"receipt"` - SolcInputHash string `json:"solcInputHash"` - StorageLayout StorageLayout `json:"storageLayout"` - TransactionHash common.Hash `json:"transactionHash"` - Userdoc json.RawMessage `json:"userdoc"` + Abi abi.ABI `json:"abi"` + Address common.Address `json:"address"` + Args []any `json:"args"` + Bytecode hexutil.Bytes `json:"bytecode"` + DeployedBytecode hexutil.Bytes `json:"deployedBytecode"` + Devdoc json.RawMessage `json:"devdoc"` + Metadata string `json:"metadata"` + Receipt Receipt `json:"receipt"` + SolcInputHash string `json:"solcInputHash"` + StorageLayout solc.StorageLayout `json:"storageLayout"` + TransactionHash common.Hash `json:"transactionHash"` + Userdoc json.RawMessage `json:"userdoc"` } // Receipt represents the receipt held in a hardhat-deploy @@ -55,31 +56,6 @@ type Log struct { Blockhash common.Hash `json:"blockHash"` } -// StorageLayout represents the storage layout of a contract -type StorageLayout struct { - Storage []StorageLayoutEntry `json:"storage"` - Types map[string]StorageLayoutType `json:"types"` -} - -// StorageLayoutEntry represents a single entry in the StorageLayout -type StorageLayoutEntry struct { - AstId uint `json:"astId"` - Contract string `json:"contract"` - Label string `json:"label"` - Offset uint `json:"offset"` - Slot uint `json:"slot,string"` - Type string `json"type"` -} - -// StorageLayoutType represents the type of storage layout -type StorageLayoutType struct { - Encoding string `json:"encoding"` - Label string `json:"label"` - NumberOfBytes string `json:"numberOfBytes"` - Key string `json:"key,omitempty"` - Value string `json:"value,omitempty"` -} - // Artifact represents a hardhat compilation artifact type Artifact struct { Format string `json:"_format"` @@ -114,10 +90,10 @@ type DebugFile struct { // BuildInfo represents a hardhat build info artifact that is created // after compilation type BuildInfo struct { - Format string `json:"_format"` - Id string `json:"id"` - SolcVersion string `json:"solcVersion"` - SolcLongVersion string `json:"solcLongVersion"` - Input json.RawMessage `json:"input"` - Output json.RawMessage `json:"output"` + Format string `json:"_format"` + Id string `json:"id"` + SolcVersion string `json:"solcVersion"` + SolcLongVersion string `json:"solcLongVersion"` + Input solc.CompilerInput `json:"input"` + Output solc.CompilerOutput `json:"output"` } diff --git a/state-surgery/solc/types.go b/state-surgery/solc/types.go new file mode 100644 index 0000000000000..99ff24ca58fd2 --- /dev/null +++ b/state-surgery/solc/types.go @@ -0,0 +1,107 @@ +package solc + +import ( + "encoding/json" + + "github.com/ethereum-optimism/optimism/l2geth/accounts/abi" +) + +type CompilerInput struct { + Language string `json:"language"` + Sources map[string]map[string]string `json:"sources"` + Settings CompilerSettings `json:"settings"` +} + +type CompilerSettings struct { + Optimizer OptimizerSettings `json:"optimizer"` + Metadata CompilerInputMetadata `json:"metadata"` + OutputSelection map[string]map[string][]string `json:"outputSelection"` + EvmVersion string `json:"evmVersion,omitempty"` + Libraries map[string]map[string]string `json:"libraries,omitempty"` +} + +type OptimizerSettings struct { + Enabled bool `json:"enabled"` + Runs uint `json:"runs"` +} + +type CompilerInputMetadata struct { + UseLiteralContent bool `json:"useLiteralContent"` +} + +type CompilerOutput struct { + Contracts map[string]CompilerOutputContracts `json:"contracts"` + Sources CompilerOutputSources `json:"sources"` +} + +type CompilerOutputContracts map[string]CompilerOutputContract + +// TODO(tynes): ignoring devdoc and userdoc for now +type CompilerOutputContract struct { + Abi abi.ABI `json:"abi"` + Evm CompilerOutputEvm `json:"evm"` + Metadata string `json:"metadata"` + StorageLayout StorageLayout `json:"storageLayout"` +} + +type StorageLayout struct { + Storage []StorageLayoutEntry `json:"storage"` + Types map[string]StorageLayoutType `json:"types"` +} + +type StorageLayoutEntry struct { + AstId uint `json:"astId"` + Contract string `json:"contract"` + Label string `json:"label"` + Offset uint `json:"offset"` + Slot uint `json:"slot,string"` + Type string `json"type"` +} + +type StorageLayoutType struct { + Encoding string `json:"encoding"` + Label string `json:"label"` + NumberOfBytes uint `json:"numberOfBytes,string"` + Key string `json:"key,omitempty"` + Value string `json:"value,omitempty"` +} + +type CompilerOutputEvm struct { + Bytecode CompilerOutputBytecode `json:"bytecode"` + DeployedBytecode CompilerOutputBytecode `json:"deployedBytecode"` + GasEstimates map[string]map[string]string `json:"gasEstimates"` + MethodIdentifiers map[string]string `json:"methodIdentifiers"` +} + +// Object must be a string because its not guranteed to be +// a hex string +type CompilerOutputBytecode struct { + Object string `json:"object"` + Opcodes string `json:"opcodes"` + SourceMap string `json:"sourceMap"` + LinkReferences LinkReferences `json:"linkReferences"` +} + +type LinkReferences map[string]LinkReference +type LinkReference map[string][]LinkReferenceOffset + +type LinkReferenceOffset struct { + Length uint `json:"length"` + Start uint `json:"start"` +} + +type CompilerOutputSources map[string]CompilerOutputSource + +type CompilerOutputSource struct { + Id uint `json:"id"` + Ast Ast `json:"ast"` +} + +type Ast struct { + AbsolutePath string `json:"absolutePath"` + ExportedSymbols map[string][]uint `json:"exportedSymbols"` + Id uint `json:"id"` + License string `json:"license"` + NodeType string `json:"nodeType"` + Nodes json.RawMessage `json:"nodes"` +} diff --git a/state-surgery/state/encoding.go b/state-surgery/state/encoding.go new file mode 100644 index 0000000000000..53be18f5cb0e4 --- /dev/null +++ b/state-surgery/state/encoding.go @@ -0,0 +1,315 @@ +package state + +import ( + "errors" + "fmt" + "math/big" + "reflect" + "strings" + + "github.com/ethereum-optimism/optimism/state-surgery/solc" + + "github.com/ethereum/go-ethereum/common" + "github.com/ethereum/go-ethereum/common/hexutil" + "github.com/ethereum/go-ethereum/crypto" +) + +// EncodeStorageKeyValue encodes the key value pair that is stored in state +// given a StorageLayoutEntry and StorageLayoutType. A single input may result +// in multiple outputs. Unknown or unimplemented types will return an error. +// Note that encoding uints is *not* overflow safe, so be sure to check +// the ABI before setting very large values +func EncodeStorageKeyValue(value any, entry solc.StorageLayoutEntry, storageType solc.StorageLayoutType) ([]*EncodedStorage, error) { + label := storageType.Label + encoded := make([]*EncodedStorage, 0) + + switch storageType.Encoding { + case "inplace": + key := encodeSlotKey(entry) + switch label { + case "bool": + val, err := EncodeBoolValue(value, entry.Offset) + if err != nil { + return nil, err + } + encoded = append(encoded, &EncodedStorage{key, val}) + case "address": + val, err := EncodeAddressValue(value, entry.Offset) + if err != nil { + return nil, err + } + encoded = append(encoded, &EncodedStorage{key, val}) + case "bytes": + return nil, fmt.Errorf("%w: %s", errUnimplemented, label) + default: + switch true { + case strings.HasPrefix(label, "contract"): + val, err := EncodeAddressValue(value, entry.Offset) + if err != nil { + return nil, err + } + encoded = append(encoded, &EncodedStorage{key, val}) + case strings.HasPrefix(label, "uint"): + val, err := EncodeUintValue(value, entry.Offset) + if err != nil { + return nil, err + } + encoded = append(encoded, &EncodedStorage{key, val}) + default: + // structs are not supported + return nil, fmt.Errorf("%w: %s", errUnimplemented, label) + } + } + case "dynamic_array": + case "bytes": + return nil, fmt.Errorf("%w: %s", errUnimplemented, label) + case "mapping": + if strings.HasPrefix(storageType.Value, "mapping") { + return nil, fmt.Errorf("%w: %s", errUnimplemented, "nested mappings") + } + + values, ok := value.(map[any]any) + if !ok { + return nil, fmt.Errorf("cannot parse mapping") + + } + + keyEncoder, err := getElementEncoder(storageType.Key) + if err != nil { + return nil, err + } + valueEncoder, err := getElementEncoder(storageType.Value) + if err != nil { + return nil, err + } + + // Mapping values have 0 offset + for rawKey, rawVal := range values { + encodedKey, err := keyEncoder(rawKey, 0) + if err != nil { + return nil, err + } + + encodedSlot := encodeSlotKey(entry) + + preimage := [64]byte{} + copy(preimage[0:32], encodedKey.Bytes()) + copy(preimage[32:64], encodedSlot.Bytes()) + + hash := crypto.Keccak256(preimage[:]) + key := common.BytesToHash(hash) + val, err := valueEncoder(rawVal, 0) + if err != nil { + return nil, err + } + encoded = append(encoded, &EncodedStorage{key, val}) + } + default: + return nil, fmt.Errorf("unknown encoding: %s", storageType.Encoding) + } + return encoded, nil +} + +// encodeSlotKey will encode the storage slot key. This does not +// support mappings. +func encodeSlotKey(entry solc.StorageLayoutEntry) common.Hash { + slot := new(big.Int).SetUint64(uint64(entry.Slot)) + return common.BigToHash(slot) +} + +// ElementEncoder is a function that can encode an element +// based on a solidity type +type ElementEncoder func(value any, offset uint) (common.Hash, error) + +// getElementEncoder will return the correct ElementEncoder +// given a solidity type. +func getElementEncoder(kind string) (ElementEncoder, error) { + switch kind { + case "t_address": + return EncodeAddressValue, nil + case "t_bool": + return EncodeBoolValue, nil + default: + if strings.HasPrefix(kind, "t_uint") { + return EncodeUintValue, nil + } + } + return nil, fmt.Errorf("unsupported type: %s", kind) +} + +// EncodeBoolValue will encode a boolean value given a storage +// offset. +func EncodeBoolValue(value any, offset uint) (common.Hash, error) { + val, err := encodeBoolValue(value) + if err != nil { + return common.Hash{}, err + } + return handleOffset(val, offset), nil +} + +// encodeBoolValue will encode a boolean value into a type +// suitable for solidity storage. +func encodeBoolValue(value any) (common.Hash, error) { + name := reflect.TypeOf(value).Name() + switch name { + case "bool": + boolean, ok := value.(bool) + if !ok { + return common.Hash{}, errInvalidType + } + if boolean { + return common.BigToHash(common.Big1), nil + } else { + return common.Hash{}, nil + } + case "string": + boolean, ok := value.(string) + if !ok { + return common.Hash{}, errInvalidType + } + if boolean == "true" { + return common.BigToHash(common.Big1), nil + } else { + return common.Hash{}, nil + } + default: + return common.Hash{}, errInvalidType + } +} + +// EncodeAddressValue will encode an address like value given a +// storage offset. +func EncodeAddressValue(value any, offset uint) (common.Hash, error) { + val, err := encodeAddressValue(value) + if err != nil { + return common.Hash{}, err + } + return handleOffset(val, offset), nil +} + +// encodeAddressValue will encode an address value into +// a type suitable for solidity storage. +func encodeAddressValue(value any) (common.Hash, error) { + name := reflect.TypeOf(value).Name() + switch name { + case "Address": + address, ok := value.(common.Address) + if !ok { + return common.Hash{}, errInvalidType + } + return address.Hash(), nil + case "string": + address, ok := value.(string) + if !ok { + return common.Hash{}, errInvalidType + } + return common.HexToAddress(address).Hash(), nil + default: + return common.Hash{}, errInvalidType + } +} + +// EncodeUintValue will encode a uint value given a storage offset +func EncodeUintValue(value any, offset uint) (common.Hash, error) { + val, err := encodeUintValue(value) + if err != nil { + return common.Hash{}, err + } + return handleOffset(val, offset), nil +} + +// encodeUintValue will encode a uint like type into a +// type suitable for solidity storage. +func encodeUintValue(value any) (common.Hash, error) { + val := reflect.ValueOf(value) + + if val.Kind() == reflect.Ptr { + val = val.Elem() + } + + name := val.Type().Name() + switch name { + case "uint": + val, ok := value.(uint) + if !ok { + return common.Hash{}, errInvalidType + } + result := new(big.Int).SetUint64((uint64(val))) + return common.BigToHash(result), nil + case "int": + val, ok := value.(int) + if !ok { + return common.Hash{}, errInvalidType + } + result := new(big.Int).SetUint64(uint64(val)) + return common.BigToHash(result), nil + case "uint64": + val, ok := value.(uint64) + if !ok { + return common.Hash{}, errInvalidType + } + result := new(big.Int).SetUint64(val) + return common.BigToHash(result), nil + case "uint32": + val, ok := value.(uint32) + if !ok { + return common.Hash{}, errInvalidType + } + result := new(big.Int).SetUint64(uint64(val)) + return common.BigToHash(result), nil + case "uint16": + val, ok := value.(uint16) + if !ok { + return common.Hash{}, errInvalidType + } + result := new(big.Int).SetUint64(uint64(val)) + return common.BigToHash(result), nil + case "uint8": + val, ok := value.(uint8) + if !ok { + return common.Hash{}, errInvalidType + } + result := new(big.Int).SetUint64(uint64(val)) + return common.BigToHash(result), nil + case "string": + val, ok := value.(string) + if !ok { + return common.Hash{}, errInvalidType + } + number, err := hexutil.DecodeBig(val) + if err != nil { + if errors.Is(err, hexutil.ErrMissingPrefix) { + number, ok = new(big.Int).SetString(val, 10) + if !ok { + return common.Hash{}, errInvalidType + } + } else if errors.Is(err, hexutil.ErrLeadingZero) { + number, ok = new(big.Int).SetString(val[2:], 16) + if !ok { + return common.Hash{}, errInvalidType + } + } + } + return common.BigToHash(number), nil + case "Int": + val, ok := value.(*big.Int) + if !ok { + return common.Hash{}, errInvalidType + } + return common.BigToHash(val), nil + default: + return common.Hash{}, errInvalidType + } +} + +// handleOffset will offset a value in storage by shifting +// it to the left. This is useful for when multiple variables +// are tightly packed in a storage slot. +func handleOffset(hash common.Hash, offset uint) common.Hash { + if offset == 0 { + return hash + } + number := hash.Big() + shifted := new(big.Int).Lsh(number, offset*8) + return common.BigToHash(shifted) +} diff --git a/state-surgery/state/memory_db.go b/state-surgery/state/memory_db.go new file mode 100644 index 0000000000000..5667ab855bda9 --- /dev/null +++ b/state-surgery/state/memory_db.go @@ -0,0 +1,311 @@ +package state + +import ( + "bytes" + "fmt" + "math/big" + "sync" + + "github.com/ethereum/go-ethereum/common" + "github.com/ethereum/go-ethereum/core" + "github.com/ethereum/go-ethereum/core/types" + "github.com/ethereum/go-ethereum/core/vm" + "github.com/ethereum/go-ethereum/crypto" +) + +var _ vm.StateDB = (*MemoryStateDB)(nil) + +var emptyCodeHash = crypto.Keccak256(nil) + +// MemoryStateDB implements geth's StateDB interface +// but operates on a core.Genesis so that a genesis.json +// can easily be created. +type MemoryStateDB struct { + rw sync.RWMutex + genesis *core.Genesis +} + +func NewMemoryStateDB(genesis *core.Genesis) *MemoryStateDB { + if genesis == nil { + genesis = core.DeveloperGenesisBlock(15, 15_000_000, common.Address{}) + } + + return &MemoryStateDB{ + genesis: genesis, + rw: sync.RWMutex{}, + } +} + +// Genesis is a getter for the underlying core.Genesis +func (db *MemoryStateDB) Genesis() *core.Genesis { + return db.genesis +} + +// GetAccount is a getter for a core.GenesisAccount found in +// the core.Genesis +func (db *MemoryStateDB) GetAccount(addr common.Address) *core.GenesisAccount { + db.rw.RLock() + defer db.rw.RUnlock() + + account, ok := db.genesis.Alloc[addr] + if !ok { + return nil + } + return &account +} + +// StateDB interface implemented below + +func (db *MemoryStateDB) CreateAccount(addr common.Address) { + db.rw.Lock() + defer db.rw.Unlock() + + db.genesis.Alloc[addr] = core.GenesisAccount{ + Code: []byte{}, + Storage: make(map[common.Hash]common.Hash), + Balance: big.NewInt(0), + Nonce: 0, + } +} + +func (db *MemoryStateDB) SubBalance(addr common.Address, amount *big.Int) { + db.rw.Lock() + defer db.rw.Unlock() + + account, ok := db.genesis.Alloc[addr] + if !ok { + panic(fmt.Sprintf("%s not in state", addr)) + } + if account.Balance.Sign() == 0 { + return + } + account.Balance = new(big.Int).Sub(account.Balance, amount) + db.genesis.Alloc[addr] = account +} + +func (db *MemoryStateDB) AddBalance(addr common.Address, amount *big.Int) { + db.rw.Lock() + defer db.rw.Unlock() + + account, ok := db.genesis.Alloc[addr] + if !ok { + panic(fmt.Sprintf("%s not in state", addr)) + } + account.Balance = new(big.Int).Add(account.Balance, amount) + db.genesis.Alloc[addr] = account +} + +func (db *MemoryStateDB) GetBalance(addr common.Address) *big.Int { + db.rw.RLock() + defer db.rw.RUnlock() + + account, ok := db.genesis.Alloc[addr] + if !ok { + return common.Big0 + } + return account.Balance +} + +func (db *MemoryStateDB) GetNonce(addr common.Address) uint64 { + db.rw.RLock() + defer db.rw.RUnlock() + + account, ok := db.genesis.Alloc[addr] + if !ok { + return 0 + } + return account.Nonce +} + +func (db *MemoryStateDB) SetNonce(addr common.Address, value uint64) { + db.rw.Lock() + defer db.rw.Unlock() + + account, ok := db.genesis.Alloc[addr] + if !ok { + return + } + account.Nonce = value + db.genesis.Alloc[addr] = account +} + +func (db *MemoryStateDB) GetCodeHash(addr common.Address) common.Hash { + db.rw.RLock() + defer db.rw.RUnlock() + + account, ok := db.genesis.Alloc[addr] + if !ok { + return common.Hash{} + } + if len(account.Code) == 0 { + return common.BytesToHash(emptyCodeHash) + } + return common.BytesToHash(crypto.Keccak256(account.Code)) +} + +func (db *MemoryStateDB) GetCode(addr common.Address) []byte { + db.rw.RLock() + defer db.rw.RUnlock() + + account, ok := db.genesis.Alloc[addr] + if !ok { + return nil + } + if bytes.Equal(crypto.Keccak256(account.Code), emptyCodeHash) { + return nil + } + return account.Code +} + +func (db *MemoryStateDB) SetCode(addr common.Address, code []byte) { + db.rw.Lock() + defer db.rw.Unlock() + + account, ok := db.genesis.Alloc[addr] + if !ok { + return + } + account.Code = code + db.genesis.Alloc[addr] = account +} + +func (db *MemoryStateDB) GetCodeSize(addr common.Address) int { + db.rw.Lock() + defer db.rw.Unlock() + + account, ok := db.genesis.Alloc[addr] + if !ok { + return 0 + } + if bytes.Equal(crypto.Keccak256(account.Code), emptyCodeHash) { + return 0 + } + return len(account.Code) +} + +func (db *MemoryStateDB) AddRefund(uint64) { + panic("AddRefund unimplemented") +} + +func (db *MemoryStateDB) SubRefund(uint64) { + panic("SubRefund unimplemented") +} + +func (db *MemoryStateDB) GetRefund() uint64 { + panic("GetRefund unimplemented") +} + +func (db *MemoryStateDB) GetCommittedState(common.Address, common.Hash) common.Hash { + panic("GetCommittedState unimplemented") +} + +func (db *MemoryStateDB) GetState(addr common.Address, key common.Hash) common.Hash { + db.rw.RLock() + defer db.rw.RUnlock() + + account, ok := db.genesis.Alloc[addr] + if !ok { + return common.Hash{} + } + return account.Storage[key] +} + +func (db *MemoryStateDB) SetState(addr common.Address, key, value common.Hash) { + db.rw.Lock() + defer db.rw.Unlock() + + account, ok := db.genesis.Alloc[addr] + if !ok { + return + } + account.Storage[key] = value + db.genesis.Alloc[addr] = account +} + +func (db *MemoryStateDB) Suicide(common.Address) bool { + panic("Suicide unimplemented") +} + +func (db *MemoryStateDB) HasSuicided(common.Address) bool { + panic("HasSuicided unimplemented") +} + +// Exist reports whether the given account exists in state. +// Notably this should also return true for suicided accounts. +func (db *MemoryStateDB) Exist(addr common.Address) bool { + db.rw.RLock() + defer db.rw.RUnlock() + + _, ok := db.genesis.Alloc[addr] + return ok +} + +// Empty returns whether the given account is empty. Empty +// is defined according to EIP161 (balance = nonce = code = 0). +func (db *MemoryStateDB) Empty(addr common.Address) bool { + db.rw.RLock() + defer db.rw.RUnlock() + + account, ok := db.genesis.Alloc[addr] + isZeroNonce := account.Nonce == 0 + isZeroValue := account.Balance.Sign() == 0 + isEmptyCode := bytes.Equal(crypto.Keccak256(account.Code), emptyCodeHash) + + return ok || (isZeroNonce && isZeroValue && isEmptyCode) +} + +func (db *MemoryStateDB) PrepareAccessList(sender common.Address, dest *common.Address, precompiles []common.Address, txAccesses types.AccessList) { + panic("PrepareAccessList unimplemented") +} + +func (db *MemoryStateDB) AddressInAccessList(addr common.Address) bool { + panic("AddressInAccessList unimplemented") +} + +func (db *MemoryStateDB) SlotInAccessList(addr common.Address, slot common.Hash) (addressOk bool, slotOk bool) { + panic("SlotInAccessList unimplemented") +} + +// AddAddressToAccessList adds the given address to the access list. This operation is safe to perform +// even if the feature/fork is not active yet +func (db *MemoryStateDB) AddAddressToAccessList(addr common.Address) { + panic("AddAddressToAccessList unimplemented") +} + +// AddSlotToAccessList adds the given (address,slot) to the access list. This operation is safe to perform +// even if the feature/fork is not active yet +func (db *MemoryStateDB) AddSlotToAccessList(addr common.Address, slot common.Hash) { + panic("AddSlotToAccessList unimplemented") +} + +func (db *MemoryStateDB) RevertToSnapshot(int) { + panic("RevertToSnapshot unimplemented") +} + +func (db *MemoryStateDB) Snapshot() int { + panic("Snapshot unimplemented") +} + +func (db *MemoryStateDB) AddLog(*types.Log) { + panic("AddLog unimplemented") +} + +func (db *MemoryStateDB) AddPreimage(common.Hash, []byte) { + panic("AddPreimage unimplemented") +} + +func (db *MemoryStateDB) ForEachStorage(addr common.Address, cb func(common.Hash, common.Hash) bool) error { + db.rw.RLock() + defer db.rw.RUnlock() + + account, ok := db.genesis.Alloc[addr] + if !ok { + return nil + } + for key, value := range account.Storage { + if !cb(key, value) { + return nil + } + } + return nil +} diff --git a/state-surgery/state/memory_db_test.go b/state-surgery/state/memory_db_test.go new file mode 100644 index 0000000000000..99e4ee62e1184 --- /dev/null +++ b/state-surgery/state/memory_db_test.go @@ -0,0 +1,63 @@ +package state_test + +import ( + "math/big" + "math/rand" + "testing" + "time" + + "github.com/ethereum-optimism/optimism/state-surgery/state" + "github.com/ethereum/go-ethereum/common" + "github.com/ethereum/go-ethereum/crypto" + "github.com/stretchr/testify/require" +) + +func TestAddBalance(t *testing.T) { + t.Parallel() + + rng := rand.New(rand.NewSource(time.Now().UnixNano())) + db := state.NewMemoryStateDB(nil) + + for i := 0; i < 100; i++ { + key, _ := crypto.GenerateKey() + addr := crypto.PubkeyToAddress(key.PublicKey) + value := new(big.Int).Rand(rng, big.NewInt(1000)) + + db.CreateAccount(addr) + db.AddBalance(addr, value) + + account := db.GetAccount(addr) + require.NotNil(t, account) + require.Equal(t, account.Balance, value) + } +} + +func TestCode(t *testing.T) { + t.Parallel() + + db := state.NewMemoryStateDB(nil) + + for i := 0; i < 100; i++ { + key, _ := crypto.GenerateKey() + addr := crypto.PubkeyToAddress(key.PublicKey) + + db.CreateAccount(addr) + + pre := db.GetCode(addr) + require.Nil(t, pre) + + code := make([]byte, rand.Intn(1024)) + rand.Read(code) + + db.SetCode(addr, code) + + post := db.GetCode(addr) + require.Equal(t, post, code) + + size := db.GetCodeSize(addr) + require.Equal(t, size, len(code)) + + codeHash := db.GetCodeHash(addr) + require.Equal(t, codeHash, common.BytesToHash(crypto.Keccak256(code))) + } +} diff --git a/state-surgery/state/state.go b/state-surgery/state/state.go new file mode 100644 index 0000000000000..4484daa810674 --- /dev/null +++ b/state-surgery/state/state.go @@ -0,0 +1,94 @@ +package state + +import ( + "errors" + "fmt" + "math/big" + + "github.com/ethereum-optimism/optimism/state-surgery/solc" + "github.com/ethereum/go-ethereum/common" +) + +// StorageValues represents the values to be set in storage. +// The key is the name of the storage variable and the value +// is the value to set in storage. +type StorageValues map[string]any + +// EncodedStorage represents the storage key and value serialized +// to be placed in Ethereum state. +type EncodedStorage struct { + Key common.Hash + Value common.Hash +} + +// EncodedStorage will encode a storage layout +func EncodeStorage(entry solc.StorageLayoutEntry, value any, storageType solc.StorageLayoutType) ([]*EncodedStorage, error) { + if storageType.NumberOfBytes > 32 { + return nil, fmt.Errorf("%s is larger than 32 bytes", entry.Label) + } + + encoded, err := EncodeStorageKeyValue(value, entry, storageType) + if err != nil { + return nil, err + } + return encoded, nil +} + +var errInvalidType = errors.New("invalid type") +var errUnimplemented = errors.New("type unimplemented") + +// ComputeStorageSlots will compute the storage slots for a given contract. +func ComputeStorageSlots(layout *solc.StorageLayout, values StorageValues) ([]*EncodedStorage, error) { + encodedStorage := make([]*EncodedStorage, 0) + + for label, value := range values { + var target solc.StorageLayoutEntry + for _, entry := range layout.Storage { + if label == entry.Label { + target = entry + } + } + if target.Label == "" { + return nil, fmt.Errorf("storage layout entry for %s not found", label) + } + + storageType := layout.Types[target.Type] + if storageType.Label == "" { + return nil, fmt.Errorf("storage type for %s not found", label) + + } + + storage, err := EncodeStorage(target, value, storageType) + if err != nil { + return nil, fmt.Errorf("cannot encode storage: %w", err) + } + + encodedStorage = append(encodedStorage, storage...) + } + + results := MergeStorage(encodedStorage) + + return results, nil +} + +// MergeStorage will combine any overlapping storage slots for +// when values are tightly packed. Do this by checking to see if any +// of the produced storage slots have a matching key, if so use a +// binary or to add the storage values together +func MergeStorage(storage []*EncodedStorage) []*EncodedStorage { + encoded := make(map[common.Hash]common.Hash) + for _, storage := range storage { + if prev, ok := encoded[storage.Key]; ok { + combined := new(big.Int).Or(prev.Big(), storage.Value.Big()) + encoded[storage.Key] = common.BigToHash(combined) + } else { + encoded[storage.Key] = storage.Value + } + } + + results := make([]*EncodedStorage, 0) + for key, val := range encoded { + results = append(results, &EncodedStorage{key, val}) + } + return results +} diff --git a/state-surgery/state/state_test.go b/state-surgery/state/state_test.go new file mode 100644 index 0000000000000..893cc510957f3 --- /dev/null +++ b/state-surgery/state/state_test.go @@ -0,0 +1,405 @@ +package state_test + +import ( + "encoding/json" + "math/big" + "os" + "testing" + + "github.com/ethereum/go-ethereum/accounts/abi/bind" + "github.com/ethereum/go-ethereum/accounts/abi/bind/backends" + "github.com/ethereum/go-ethereum/common" + "github.com/ethereum/go-ethereum/core" + "github.com/ethereum/go-ethereum/crypto" + + "github.com/ethereum-optimism/optimism/state-surgery/solc" + "github.com/ethereum-optimism/optimism/state-surgery/state" + "github.com/ethereum-optimism/optimism/state-surgery/state/testdata" + + "github.com/stretchr/testify/require" +) + +var ( + // layout is the storage layout used in tests + layout solc.StorageLayout + // testKey is the same test key that geth uses + testKey, _ = crypto.HexToECDSA("b71c71a67e1177ad4e901695e1b4b9ee17ae16c6668d313eac2f96dbcda3f291") + // chainID is the chain id used for simulated backends + chainID = big.NewInt(1337) +) + +// Read the test data from disk asap +func init() { + data, err := os.ReadFile("./testdata/layout.json") + if err != nil { + panic("layout.json not found") + + } + if err := json.Unmarshal(data, &layout); err != nil { + panic("cannot unmarshal storage layout") + } +} + +func TestSetAndGetStorageSlots(t *testing.T) { + values := state.StorageValues{} + values["_uint256"] = new(big.Int).SetUint64(0xafff_ffff_ffff_ffff) + values["_address"] = common.HexToAddress("0xEA674fdDe714fd979de3EdF0F56AA9716B898ec8") + values["_bool"] = true + values["offset0"] = uint8(0xaa) + values["offset1"] = uint8(0xbb) + values["offset2"] = uint16(0x0c0c) + values["offset3"] = uint32(0xf33d35) + values["offset4"] = uint64(0xd34dd34d00) + values["offset5"] = new(big.Int).SetUint64(0x43ad0043ad0043ad) + + addresses := make(map[any]any) + addresses[big.NewInt(1)] = common.Address{19: 0xff} + + values["addresses"] = addresses + + slots, err := state.ComputeStorageSlots(&layout, values) + require.Nil(t, err) + + backend := backends.NewSimulatedBackend( + core.GenesisAlloc{ + crypto.PubkeyToAddress(testKey.PublicKey): {Balance: big.NewInt(10000000000000000)}, + }, + 15000000, + ) + opts, err := bind.NewKeyedTransactorWithChainID(testKey, chainID) + require.Nil(t, err) + + _, _, contract, err := testdata.DeployTestdata(opts, backend) + require.Nil(t, err) + backend.Commit() + + // Call each of the methods to make sure that they are set to their 0 values + testContractStateValuesAreEmpty(t, contract) + + // Send transactions through the set storage API on the contract + for _, slot := range slots { + _, err := contract.SetStorage(opts, slot.Key, slot.Value) + require.Nil(t, err) + } + backend.Commit() + + testContractStateValuesAreSet(t, contract, values) + + // Call the get storage API on the contract to double check + // that the storage slots have been set correctly + for _, slot := range slots { + value, err := contract.GetStorage(&bind.CallOpts{}, slot.Key) + require.Nil(t, err) + require.Equal(t, value[:], slot.Value.Bytes()) + } +} + +// Ensure that all the storage variables are set after setting storage +// through the contract +func testContractStateValuesAreSet(t *testing.T, contract *testdata.Testdata, values state.StorageValues) { +OUTER: + for key, value := range values { + var res any + var err error + switch key { + case "_uint256": + res, err = contract.Uint256(&bind.CallOpts{}) + case "_address": + res, err = contract.Address(&bind.CallOpts{}) + case "_bool": + res, err = contract.Bool(&bind.CallOpts{}) + case "offset0": + res, err = contract.Offset0(&bind.CallOpts{}) + case "offset1": + res, err = contract.Offset1(&bind.CallOpts{}) + case "offset2": + res, err = contract.Offset2(&bind.CallOpts{}) + case "offset3": + res, err = contract.Offset3(&bind.CallOpts{}) + case "offset4": + res, err = contract.Offset4(&bind.CallOpts{}) + case "offset5": + res, err = contract.Offset5(&bind.CallOpts{}) + case "addresses": + addrs, ok := value.(map[any]any) + require.Equal(t, ok, true) + for mapKey, mapVal := range addrs { + res, err = contract.Addresses(&bind.CallOpts{}, mapKey.(*big.Int)) + require.Nil(t, err) + require.Equal(t, mapVal, res) + continue OUTER + } + default: + require.Fail(t, "Unknown variable label", key) + } + require.Nil(t, err) + require.Equal(t, res, value) + } +} + +func testContractStateValuesAreEmpty(t *testing.T, contract *testdata.Testdata) { + addr, err := contract.Address(&bind.CallOpts{}) + require.Nil(t, err) + require.Equal(t, addr, common.Address{}) + + boolean, err := contract.Bool(&bind.CallOpts{}) + require.Nil(t, err) + require.Equal(t, boolean, false) + + uint256, err := contract.Uint256(&bind.CallOpts{}) + require.Nil(t, err) + require.Equal(t, uint256.Uint64(), uint64(0)) + + offset0, err := contract.Offset0(&bind.CallOpts{}) + require.Nil(t, err) + require.Equal(t, offset0, uint8(0)) + + offset1, err := contract.Offset1(&bind.CallOpts{}) + require.Nil(t, err) + require.Equal(t, offset1, uint8(0)) + + offset2, err := contract.Offset2(&bind.CallOpts{}) + require.Nil(t, err) + require.Equal(t, offset2, uint16(0)) + + offset3, err := contract.Offset3(&bind.CallOpts{}) + require.Nil(t, err) + require.Equal(t, offset3, uint32(0)) + + offset4, err := contract.Offset4(&bind.CallOpts{}) + require.Nil(t, err) + require.Equal(t, offset4, uint64(0)) + + offset5, err := contract.Offset5(&bind.CallOpts{}) + require.Nil(t, err) + require.Equal(t, offset5.Uint64(), uint64(0)) +} + +func TestMergeStorage(t *testing.T) { + cases := []struct { + input []*state.EncodedStorage + expect []*state.EncodedStorage + }{ + { + // One input should be the same result + input: []*state.EncodedStorage{ + { + Key: common.Hash{}, + Value: common.Hash{}, + }, + }, + expect: []*state.EncodedStorage{ + { + Key: common.Hash{}, + Value: common.Hash{}, + }, + }, + }, + { + // Two duplicate inputs should be merged + input: []*state.EncodedStorage{ + { + Key: common.Hash{1}, + Value: common.Hash{}, + }, + { + Key: common.Hash{1}, + Value: common.Hash{}, + }, + }, + expect: []*state.EncodedStorage{ + { + Key: common.Hash{1}, + Value: common.Hash{}, + }, + }, + }, + { + // Two different inputs should be the same result + input: []*state.EncodedStorage{ + { + Key: common.Hash{1}, + Value: common.Hash{}, + }, + { + Key: common.Hash{2}, + Value: common.Hash{}, + }, + }, + expect: []*state.EncodedStorage{ + { + Key: common.Hash{1}, + Value: common.Hash{}, + }, + { + Key: common.Hash{2}, + Value: common.Hash{}, + }, + }, + }, + { + // Two matching keys should be merged bitwise + input: []*state.EncodedStorage{ + { + Key: common.Hash{}, + Value: common.Hash{0x00, 0x01}, + }, + { + Key: common.Hash{}, + Value: common.Hash{0x02, 0x00}, + }, + }, + expect: []*state.EncodedStorage{ + { + Key: common.Hash{}, + Value: common.Hash{0x02, 0x01}, + }, + }, + }, + } + + for _, test := range cases { + got := state.MergeStorage(test.input) + require.Equal(t, got, test.expect) + } +} + +func TestEncodeUintValue(t *testing.T) { + cases := []struct { + number any + offset uint + expect common.Hash + }{ + { + number: 0, + offset: 0, + expect: common.Hash{}, + }, + { + number: big.NewInt(1), + offset: 0, + expect: common.Hash{31: 0x01}, + }, + { + number: uint64(2), + offset: 0, + expect: common.Hash{31: 0x02}, + }, + { + number: uint8(3), + offset: 0, + expect: common.Hash{31: 0x03}, + }, + { + number: uint16(4), + offset: 0, + expect: common.Hash{31: 0x04}, + }, + { + number: uint32(5), + offset: 0, + expect: common.Hash{31: 0x05}, + }, + { + number: int(6), + offset: 0, + expect: common.Hash{31: 0x06}, + }, + { + number: 1, + offset: 1, + expect: common.Hash{30: 0x01}, + }, + { + number: 1, + offset: 10, + expect: common.Hash{21: 0x01}, + }, + } + + for _, test := range cases { + got, err := state.EncodeUintValue(test.number, test.offset) + require.Nil(t, err) + require.Equal(t, got, test.expect) + } +} + +func TestEncodeBoolValue(t *testing.T) { + cases := []struct { + boolean any + offset uint + expect common.Hash + }{ + { + boolean: true, + offset: 0, + expect: common.Hash{31: 0x01}, + }, + { + boolean: false, + offset: 0, + expect: common.Hash{}, + }, + { + boolean: true, + offset: 1, + expect: common.Hash{30: 0x01}, + }, + { + boolean: false, + offset: 1, + expect: common.Hash{}, + }, + { + boolean: "true", + offset: 0, + expect: common.Hash{31: 0x01}, + }, + { + boolean: "false", + offset: 0, + expect: common.Hash{}, + }, + } + + for _, test := range cases { + got, err := state.EncodeBoolValue(test.boolean, test.offset) + require.Nil(t, err) + require.Equal(t, got, test.expect) + } +} + +func TestEncodeAddressValue(t *testing.T) { + cases := []struct { + addr any + offset uint + expect common.Hash + }{ + { + addr: common.Address{}, + offset: 0, + expect: common.Hash{}, + }, + { + addr: common.Address{0x01}, + offset: 0, + expect: common.Hash{12: 0x01}, + }, + { + addr: "0x829BD824B016326A401d083B33D092293333A830", + offset: 0, + expect: common.HexToHash("0x829BD824B016326A401d083B33D092293333A830"), + }, + { + addr: common.Address{19: 0x01}, + offset: 1, + expect: common.Hash{30: 0x01}, + }, + } + + for _, test := range cases { + got, err := state.EncodeAddressValue(test.addr, test.offset) + require.Nil(t, err) + require.Equal(t, got, test.expect) + } +} diff --git a/state-surgery/state/testdata/contract.go b/state-surgery/state/testdata/contract.go new file mode 100644 index 0000000000000..00b6646bbad80 --- /dev/null +++ b/state-surgery/state/testdata/contract.go @@ -0,0 +1,565 @@ +// Code generated - DO NOT EDIT. +// This file is a generated binding and any manual changes will be lost. + +package testdata + +import ( + "errors" + "math/big" + "strings" + + ethereum "github.com/ethereum/go-ethereum" + "github.com/ethereum/go-ethereum/accounts/abi" + "github.com/ethereum/go-ethereum/accounts/abi/bind" + "github.com/ethereum/go-ethereum/common" + "github.com/ethereum/go-ethereum/core/types" + "github.com/ethereum/go-ethereum/event" +) + +// Reference imports to suppress errors if they are not otherwise used. +var ( + _ = errors.New + _ = big.NewInt + _ = strings.NewReader + _ = ethereum.NotFound + _ = bind.Bind + _ = common.Big1 + _ = types.BloomLookup + _ = event.NewSubscription +) + +// TestdataMetaData contains all meta data concerning the Testdata contract. +var TestdataMetaData = &bind.MetaData{ + ABI: "[{\"inputs\":[],\"name\":\"_address\",\"outputs\":[{\"internalType\":\"address\",\"name\":\"\",\"type\":\"address\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"_bool\",\"outputs\":[{\"internalType\":\"bool\",\"name\":\"\",\"type\":\"bool\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"_uint256\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"name\":\"addresses\",\"outputs\":[{\"internalType\":\"address\",\"name\":\"\",\"type\":\"address\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"bytes32\",\"name\":\"key\",\"type\":\"bytes32\"}],\"name\":\"getStorage\",\"outputs\":[{\"internalType\":\"bytes32\",\"name\":\"\",\"type\":\"bytes32\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"offset0\",\"outputs\":[{\"internalType\":\"uint8\",\"name\":\"\",\"type\":\"uint8\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"offset1\",\"outputs\":[{\"internalType\":\"uint8\",\"name\":\"\",\"type\":\"uint8\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"offset2\",\"outputs\":[{\"internalType\":\"uint16\",\"name\":\"\",\"type\":\"uint16\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"offset3\",\"outputs\":[{\"internalType\":\"uint32\",\"name\":\"\",\"type\":\"uint32\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"offset4\",\"outputs\":[{\"internalType\":\"uint64\",\"name\":\"\",\"type\":\"uint64\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"offset5\",\"outputs\":[{\"internalType\":\"uint128\",\"name\":\"\",\"type\":\"uint128\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"bytes32\",\"name\":\"key\",\"type\":\"bytes32\"},{\"internalType\":\"bytes32\",\"name\":\"value\",\"type\":\"bytes32\"}],\"name\":\"setStorage\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"}]", + Bin: "0x608060405234801561001057600080fd5b506102a4806100206000396000f3fe608060405234801561001057600080fd5b50600436106100b45760003560e01c8063502a6c5e11610071578063502a6c5e1461019a5780635e006859146101cc5780639b0b0fda146101d55780639e6ba9c2146101e9578063a753307d14610206578063edf26d9b1461023357600080fd5b8063099ea180146100b957806309f395f1146100dd57806318bad217146100ef57806332da25e11461011a578063350e81cc146101535780634ba664e71461017a575b600080fd5b6004546100c69060ff1681565b60405160ff90911681526020015b60405180910390f35b6004546100c690610100900460ff1681565b600054610102906001600160a01b031681565b6040516001600160a01b0390911681526020016100d4565b60045461013a9068010000000000000000900467ffffffffffffffff1681565b60405167ffffffffffffffff90911681526020016100d4565b6004546101679062010000900461ffff1681565b60405161ffff90911681526020016100d4565b61018c61018836600461025c565b5490565b6040519081526020016100d4565b6004546101b490600160801b90046001600160801b031681565b6040516001600160801b0390911681526020016100d4565b61018c60035481565b6101e76101e3366004610275565b9055565b005b6002546101f69060ff1681565b60405190151581526020016100d4565b60045461021e90640100000000900463ffffffff1681565b60405163ffffffff90911681526020016100d4565b61010261024136600461025c565b6001602052600090815260409020546001600160a01b031681565b60006020828403121561026e57600080fd5b5035919050565b6000806040838503121561028857600080fd5b5050803592602090910135915056fea164736f6c634300080f000a", +} + +// TestdataABI is the input ABI used to generate the binding from. +// Deprecated: Use TestdataMetaData.ABI instead. +var TestdataABI = TestdataMetaData.ABI + +// TestdataBin is the compiled bytecode used for deploying new contracts. +// Deprecated: Use TestdataMetaData.Bin instead. +var TestdataBin = TestdataMetaData.Bin + +// DeployTestdata deploys a new Ethereum contract, binding an instance of Testdata to it. +func DeployTestdata(auth *bind.TransactOpts, backend bind.ContractBackend) (common.Address, *types.Transaction, *Testdata, error) { + parsed, err := TestdataMetaData.GetAbi() + if err != nil { + return common.Address{}, nil, nil, err + } + if parsed == nil { + return common.Address{}, nil, nil, errors.New("GetABI returned nil") + } + + address, tx, contract, err := bind.DeployContract(auth, *parsed, common.FromHex(TestdataBin), backend) + if err != nil { + return common.Address{}, nil, nil, err + } + return address, tx, &Testdata{TestdataCaller: TestdataCaller{contract: contract}, TestdataTransactor: TestdataTransactor{contract: contract}, TestdataFilterer: TestdataFilterer{contract: contract}}, nil +} + +// Testdata is an auto generated Go binding around an Ethereum contract. +type Testdata struct { + TestdataCaller // Read-only binding to the contract + TestdataTransactor // Write-only binding to the contract + TestdataFilterer // Log filterer for contract events +} + +// TestdataCaller is an auto generated read-only Go binding around an Ethereum contract. +type TestdataCaller struct { + contract *bind.BoundContract // Generic contract wrapper for the low level calls +} + +// TestdataTransactor is an auto generated write-only Go binding around an Ethereum contract. +type TestdataTransactor struct { + contract *bind.BoundContract // Generic contract wrapper for the low level calls +} + +// TestdataFilterer is an auto generated log filtering Go binding around an Ethereum contract events. +type TestdataFilterer struct { + contract *bind.BoundContract // Generic contract wrapper for the low level calls +} + +// TestdataSession is an auto generated Go binding around an Ethereum contract, +// with pre-set call and transact options. +type TestdataSession struct { + Contract *Testdata // Generic contract binding to set the session for + CallOpts bind.CallOpts // Call options to use throughout this session + TransactOpts bind.TransactOpts // Transaction auth options to use throughout this session +} + +// TestdataCallerSession is an auto generated read-only Go binding around an Ethereum contract, +// with pre-set call options. +type TestdataCallerSession struct { + Contract *TestdataCaller // Generic contract caller binding to set the session for + CallOpts bind.CallOpts // Call options to use throughout this session +} + +// TestdataTransactorSession is an auto generated write-only Go binding around an Ethereum contract, +// with pre-set transact options. +type TestdataTransactorSession struct { + Contract *TestdataTransactor // Generic contract transactor binding to set the session for + TransactOpts bind.TransactOpts // Transaction auth options to use throughout this session +} + +// TestdataRaw is an auto generated low-level Go binding around an Ethereum contract. +type TestdataRaw struct { + Contract *Testdata // Generic contract binding to access the raw methods on +} + +// TestdataCallerRaw is an auto generated low-level read-only Go binding around an Ethereum contract. +type TestdataCallerRaw struct { + Contract *TestdataCaller // Generic read-only contract binding to access the raw methods on +} + +// TestdataTransactorRaw is an auto generated low-level write-only Go binding around an Ethereum contract. +type TestdataTransactorRaw struct { + Contract *TestdataTransactor // Generic write-only contract binding to access the raw methods on +} + +// NewTestdata creates a new instance of Testdata, bound to a specific deployed contract. +func NewTestdata(address common.Address, backend bind.ContractBackend) (*Testdata, error) { + contract, err := bindTestdata(address, backend, backend, backend) + if err != nil { + return nil, err + } + return &Testdata{TestdataCaller: TestdataCaller{contract: contract}, TestdataTransactor: TestdataTransactor{contract: contract}, TestdataFilterer: TestdataFilterer{contract: contract}}, nil +} + +// NewTestdataCaller creates a new read-only instance of Testdata, bound to a specific deployed contract. +func NewTestdataCaller(address common.Address, caller bind.ContractCaller) (*TestdataCaller, error) { + contract, err := bindTestdata(address, caller, nil, nil) + if err != nil { + return nil, err + } + return &TestdataCaller{contract: contract}, nil +} + +// NewTestdataTransactor creates a new write-only instance of Testdata, bound to a specific deployed contract. +func NewTestdataTransactor(address common.Address, transactor bind.ContractTransactor) (*TestdataTransactor, error) { + contract, err := bindTestdata(address, nil, transactor, nil) + if err != nil { + return nil, err + } + return &TestdataTransactor{contract: contract}, nil +} + +// NewTestdataFilterer creates a new log filterer instance of Testdata, bound to a specific deployed contract. +func NewTestdataFilterer(address common.Address, filterer bind.ContractFilterer) (*TestdataFilterer, error) { + contract, err := bindTestdata(address, nil, nil, filterer) + if err != nil { + return nil, err + } + return &TestdataFilterer{contract: contract}, nil +} + +// bindTestdata binds a generic wrapper to an already deployed contract. +func bindTestdata(address common.Address, caller bind.ContractCaller, transactor bind.ContractTransactor, filterer bind.ContractFilterer) (*bind.BoundContract, error) { + parsed, err := abi.JSON(strings.NewReader(TestdataABI)) + if err != nil { + return nil, err + } + return bind.NewBoundContract(address, parsed, caller, transactor, filterer), nil +} + +// Call invokes the (constant) contract method with params as input values and +// sets the output to result. The result type might be a single field for simple +// returns, a slice of interfaces for anonymous returns and a struct for named +// returns. +func (_Testdata *TestdataRaw) Call(opts *bind.CallOpts, result *[]interface{}, method string, params ...interface{}) error { + return _Testdata.Contract.TestdataCaller.contract.Call(opts, result, method, params...) +} + +// Transfer initiates a plain transaction to move funds to the contract, calling +// its default method if one is available. +func (_Testdata *TestdataRaw) Transfer(opts *bind.TransactOpts) (*types.Transaction, error) { + return _Testdata.Contract.TestdataTransactor.contract.Transfer(opts) +} + +// Transact invokes the (paid) contract method with params as input values. +func (_Testdata *TestdataRaw) Transact(opts *bind.TransactOpts, method string, params ...interface{}) (*types.Transaction, error) { + return _Testdata.Contract.TestdataTransactor.contract.Transact(opts, method, params...) +} + +// Call invokes the (constant) contract method with params as input values and +// sets the output to result. The result type might be a single field for simple +// returns, a slice of interfaces for anonymous returns and a struct for named +// returns. +func (_Testdata *TestdataCallerRaw) Call(opts *bind.CallOpts, result *[]interface{}, method string, params ...interface{}) error { + return _Testdata.Contract.contract.Call(opts, result, method, params...) +} + +// Transfer initiates a plain transaction to move funds to the contract, calling +// its default method if one is available. +func (_Testdata *TestdataTransactorRaw) Transfer(opts *bind.TransactOpts) (*types.Transaction, error) { + return _Testdata.Contract.contract.Transfer(opts) +} + +// Transact invokes the (paid) contract method with params as input values. +func (_Testdata *TestdataTransactorRaw) Transact(opts *bind.TransactOpts, method string, params ...interface{}) (*types.Transaction, error) { + return _Testdata.Contract.contract.Transact(opts, method, params...) +} + +// Address is a free data retrieval call binding the contract method 0x18bad217. +// +// Solidity: function _address() view returns(address) +func (_Testdata *TestdataCaller) Address(opts *bind.CallOpts) (common.Address, error) { + var out []interface{} + err := _Testdata.contract.Call(opts, &out, "_address") + + if err != nil { + return *new(common.Address), err + } + + out0 := *abi.ConvertType(out[0], new(common.Address)).(*common.Address) + + return out0, err + +} + +// Address is a free data retrieval call binding the contract method 0x18bad217. +// +// Solidity: function _address() view returns(address) +func (_Testdata *TestdataSession) Address() (common.Address, error) { + return _Testdata.Contract.Address(&_Testdata.CallOpts) +} + +// Address is a free data retrieval call binding the contract method 0x18bad217. +// +// Solidity: function _address() view returns(address) +func (_Testdata *TestdataCallerSession) Address() (common.Address, error) { + return _Testdata.Contract.Address(&_Testdata.CallOpts) +} + +// Bool is a free data retrieval call binding the contract method 0x9e6ba9c2. +// +// Solidity: function _bool() view returns(bool) +func (_Testdata *TestdataCaller) Bool(opts *bind.CallOpts) (bool, error) { + var out []interface{} + err := _Testdata.contract.Call(opts, &out, "_bool") + + if err != nil { + return *new(bool), err + } + + out0 := *abi.ConvertType(out[0], new(bool)).(*bool) + + return out0, err + +} + +// Bool is a free data retrieval call binding the contract method 0x9e6ba9c2. +// +// Solidity: function _bool() view returns(bool) +func (_Testdata *TestdataSession) Bool() (bool, error) { + return _Testdata.Contract.Bool(&_Testdata.CallOpts) +} + +// Bool is a free data retrieval call binding the contract method 0x9e6ba9c2. +// +// Solidity: function _bool() view returns(bool) +func (_Testdata *TestdataCallerSession) Bool() (bool, error) { + return _Testdata.Contract.Bool(&_Testdata.CallOpts) +} + +// Uint256 is a free data retrieval call binding the contract method 0x5e006859. +// +// Solidity: function _uint256() view returns(uint256) +func (_Testdata *TestdataCaller) Uint256(opts *bind.CallOpts) (*big.Int, error) { + var out []interface{} + err := _Testdata.contract.Call(opts, &out, "_uint256") + + if err != nil { + return *new(*big.Int), err + } + + out0 := *abi.ConvertType(out[0], new(*big.Int)).(**big.Int) + + return out0, err + +} + +// Uint256 is a free data retrieval call binding the contract method 0x5e006859. +// +// Solidity: function _uint256() view returns(uint256) +func (_Testdata *TestdataSession) Uint256() (*big.Int, error) { + return _Testdata.Contract.Uint256(&_Testdata.CallOpts) +} + +// Uint256 is a free data retrieval call binding the contract method 0x5e006859. +// +// Solidity: function _uint256() view returns(uint256) +func (_Testdata *TestdataCallerSession) Uint256() (*big.Int, error) { + return _Testdata.Contract.Uint256(&_Testdata.CallOpts) +} + +// Addresses is a free data retrieval call binding the contract method 0xedf26d9b. +// +// Solidity: function addresses(uint256 ) view returns(address) +func (_Testdata *TestdataCaller) Addresses(opts *bind.CallOpts, arg0 *big.Int) (common.Address, error) { + var out []interface{} + err := _Testdata.contract.Call(opts, &out, "addresses", arg0) + + if err != nil { + return *new(common.Address), err + } + + out0 := *abi.ConvertType(out[0], new(common.Address)).(*common.Address) + + return out0, err + +} + +// Addresses is a free data retrieval call binding the contract method 0xedf26d9b. +// +// Solidity: function addresses(uint256 ) view returns(address) +func (_Testdata *TestdataSession) Addresses(arg0 *big.Int) (common.Address, error) { + return _Testdata.Contract.Addresses(&_Testdata.CallOpts, arg0) +} + +// Addresses is a free data retrieval call binding the contract method 0xedf26d9b. +// +// Solidity: function addresses(uint256 ) view returns(address) +func (_Testdata *TestdataCallerSession) Addresses(arg0 *big.Int) (common.Address, error) { + return _Testdata.Contract.Addresses(&_Testdata.CallOpts, arg0) +} + +// GetStorage is a free data retrieval call binding the contract method 0x4ba664e7. +// +// Solidity: function getStorage(bytes32 key) view returns(bytes32) +func (_Testdata *TestdataCaller) GetStorage(opts *bind.CallOpts, key [32]byte) ([32]byte, error) { + var out []interface{} + err := _Testdata.contract.Call(opts, &out, "getStorage", key) + + if err != nil { + return *new([32]byte), err + } + + out0 := *abi.ConvertType(out[0], new([32]byte)).(*[32]byte) + + return out0, err + +} + +// GetStorage is a free data retrieval call binding the contract method 0x4ba664e7. +// +// Solidity: function getStorage(bytes32 key) view returns(bytes32) +func (_Testdata *TestdataSession) GetStorage(key [32]byte) ([32]byte, error) { + return _Testdata.Contract.GetStorage(&_Testdata.CallOpts, key) +} + +// GetStorage is a free data retrieval call binding the contract method 0x4ba664e7. +// +// Solidity: function getStorage(bytes32 key) view returns(bytes32) +func (_Testdata *TestdataCallerSession) GetStorage(key [32]byte) ([32]byte, error) { + return _Testdata.Contract.GetStorage(&_Testdata.CallOpts, key) +} + +// Offset0 is a free data retrieval call binding the contract method 0x099ea180. +// +// Solidity: function offset0() view returns(uint8) +func (_Testdata *TestdataCaller) Offset0(opts *bind.CallOpts) (uint8, error) { + var out []interface{} + err := _Testdata.contract.Call(opts, &out, "offset0") + + if err != nil { + return *new(uint8), err + } + + out0 := *abi.ConvertType(out[0], new(uint8)).(*uint8) + + return out0, err + +} + +// Offset0 is a free data retrieval call binding the contract method 0x099ea180. +// +// Solidity: function offset0() view returns(uint8) +func (_Testdata *TestdataSession) Offset0() (uint8, error) { + return _Testdata.Contract.Offset0(&_Testdata.CallOpts) +} + +// Offset0 is a free data retrieval call binding the contract method 0x099ea180. +// +// Solidity: function offset0() view returns(uint8) +func (_Testdata *TestdataCallerSession) Offset0() (uint8, error) { + return _Testdata.Contract.Offset0(&_Testdata.CallOpts) +} + +// Offset1 is a free data retrieval call binding the contract method 0x09f395f1. +// +// Solidity: function offset1() view returns(uint8) +func (_Testdata *TestdataCaller) Offset1(opts *bind.CallOpts) (uint8, error) { + var out []interface{} + err := _Testdata.contract.Call(opts, &out, "offset1") + + if err != nil { + return *new(uint8), err + } + + out0 := *abi.ConvertType(out[0], new(uint8)).(*uint8) + + return out0, err + +} + +// Offset1 is a free data retrieval call binding the contract method 0x09f395f1. +// +// Solidity: function offset1() view returns(uint8) +func (_Testdata *TestdataSession) Offset1() (uint8, error) { + return _Testdata.Contract.Offset1(&_Testdata.CallOpts) +} + +// Offset1 is a free data retrieval call binding the contract method 0x09f395f1. +// +// Solidity: function offset1() view returns(uint8) +func (_Testdata *TestdataCallerSession) Offset1() (uint8, error) { + return _Testdata.Contract.Offset1(&_Testdata.CallOpts) +} + +// Offset2 is a free data retrieval call binding the contract method 0x350e81cc. +// +// Solidity: function offset2() view returns(uint16) +func (_Testdata *TestdataCaller) Offset2(opts *bind.CallOpts) (uint16, error) { + var out []interface{} + err := _Testdata.contract.Call(opts, &out, "offset2") + + if err != nil { + return *new(uint16), err + } + + out0 := *abi.ConvertType(out[0], new(uint16)).(*uint16) + + return out0, err + +} + +// Offset2 is a free data retrieval call binding the contract method 0x350e81cc. +// +// Solidity: function offset2() view returns(uint16) +func (_Testdata *TestdataSession) Offset2() (uint16, error) { + return _Testdata.Contract.Offset2(&_Testdata.CallOpts) +} + +// Offset2 is a free data retrieval call binding the contract method 0x350e81cc. +// +// Solidity: function offset2() view returns(uint16) +func (_Testdata *TestdataCallerSession) Offset2() (uint16, error) { + return _Testdata.Contract.Offset2(&_Testdata.CallOpts) +} + +// Offset3 is a free data retrieval call binding the contract method 0xa753307d. +// +// Solidity: function offset3() view returns(uint32) +func (_Testdata *TestdataCaller) Offset3(opts *bind.CallOpts) (uint32, error) { + var out []interface{} + err := _Testdata.contract.Call(opts, &out, "offset3") + + if err != nil { + return *new(uint32), err + } + + out0 := *abi.ConvertType(out[0], new(uint32)).(*uint32) + + return out0, err + +} + +// Offset3 is a free data retrieval call binding the contract method 0xa753307d. +// +// Solidity: function offset3() view returns(uint32) +func (_Testdata *TestdataSession) Offset3() (uint32, error) { + return _Testdata.Contract.Offset3(&_Testdata.CallOpts) +} + +// Offset3 is a free data retrieval call binding the contract method 0xa753307d. +// +// Solidity: function offset3() view returns(uint32) +func (_Testdata *TestdataCallerSession) Offset3() (uint32, error) { + return _Testdata.Contract.Offset3(&_Testdata.CallOpts) +} + +// Offset4 is a free data retrieval call binding the contract method 0x32da25e1. +// +// Solidity: function offset4() view returns(uint64) +func (_Testdata *TestdataCaller) Offset4(opts *bind.CallOpts) (uint64, error) { + var out []interface{} + err := _Testdata.contract.Call(opts, &out, "offset4") + + if err != nil { + return *new(uint64), err + } + + out0 := *abi.ConvertType(out[0], new(uint64)).(*uint64) + + return out0, err + +} + +// Offset4 is a free data retrieval call binding the contract method 0x32da25e1. +// +// Solidity: function offset4() view returns(uint64) +func (_Testdata *TestdataSession) Offset4() (uint64, error) { + return _Testdata.Contract.Offset4(&_Testdata.CallOpts) +} + +// Offset4 is a free data retrieval call binding the contract method 0x32da25e1. +// +// Solidity: function offset4() view returns(uint64) +func (_Testdata *TestdataCallerSession) Offset4() (uint64, error) { + return _Testdata.Contract.Offset4(&_Testdata.CallOpts) +} + +// Offset5 is a free data retrieval call binding the contract method 0x502a6c5e. +// +// Solidity: function offset5() view returns(uint128) +func (_Testdata *TestdataCaller) Offset5(opts *bind.CallOpts) (*big.Int, error) { + var out []interface{} + err := _Testdata.contract.Call(opts, &out, "offset5") + + if err != nil { + return *new(*big.Int), err + } + + out0 := *abi.ConvertType(out[0], new(*big.Int)).(**big.Int) + + return out0, err + +} + +// Offset5 is a free data retrieval call binding the contract method 0x502a6c5e. +// +// Solidity: function offset5() view returns(uint128) +func (_Testdata *TestdataSession) Offset5() (*big.Int, error) { + return _Testdata.Contract.Offset5(&_Testdata.CallOpts) +} + +// Offset5 is a free data retrieval call binding the contract method 0x502a6c5e. +// +// Solidity: function offset5() view returns(uint128) +func (_Testdata *TestdataCallerSession) Offset5() (*big.Int, error) { + return _Testdata.Contract.Offset5(&_Testdata.CallOpts) +} + +// SetStorage is a paid mutator transaction binding the contract method 0x9b0b0fda. +// +// Solidity: function setStorage(bytes32 key, bytes32 value) returns() +func (_Testdata *TestdataTransactor) SetStorage(opts *bind.TransactOpts, key [32]byte, value [32]byte) (*types.Transaction, error) { + return _Testdata.contract.Transact(opts, "setStorage", key, value) +} + +// SetStorage is a paid mutator transaction binding the contract method 0x9b0b0fda. +// +// Solidity: function setStorage(bytes32 key, bytes32 value) returns() +func (_Testdata *TestdataSession) SetStorage(key [32]byte, value [32]byte) (*types.Transaction, error) { + return _Testdata.Contract.SetStorage(&_Testdata.TransactOpts, key, value) +} + +// SetStorage is a paid mutator transaction binding the contract method 0x9b0b0fda. +// +// Solidity: function setStorage(bytes32 key, bytes32 value) returns() +func (_Testdata *TestdataTransactorSession) SetStorage(key [32]byte, value [32]byte) (*types.Transaction, error) { + return _Testdata.Contract.SetStorage(&_Testdata.TransactOpts, key, value) +} + diff --git a/state-surgery/state/testdata/layout.json b/state-surgery/state/testdata/layout.json new file mode 100644 index 0000000000000..55dd268c22973 --- /dev/null +++ b/state-surgery/state/testdata/layout.json @@ -0,0 +1,133 @@ +{ + "storage": [ + { + "astId": 3, + "contract": "contracts/HelloWorld.sol:HelloWorld", + "label": "_address", + "offset": 0, + "slot": "0", + "type": "t_address" + }, + { + "astId": 7, + "contract": "contracts/HelloWorld.sol:HelloWorld", + "label": "addresses", + "offset": 0, + "slot": "1", + "type": "t_mapping(t_uint256,t_address)" + }, + { + "astId": 9, + "contract": "contracts/HelloWorld.sol:HelloWorld", + "label": "_bool", + "offset": 0, + "slot": "2", + "type": "t_bool" + }, + { + "astId": 11, + "contract": "contracts/HelloWorld.sol:HelloWorld", + "label": "_uint256", + "offset": 0, + "slot": "3", + "type": "t_uint256" + }, + { + "astId": 13, + "contract": "contracts/HelloWorld.sol:HelloWorld", + "label": "offset0", + "offset": 0, + "slot": "4", + "type": "t_uint8" + }, + { + "astId": 15, + "contract": "contracts/HelloWorld.sol:HelloWorld", + "label": "offset1", + "offset": 1, + "slot": "4", + "type": "t_uint8" + }, + { + "astId": 17, + "contract": "contracts/HelloWorld.sol:HelloWorld", + "label": "offset2", + "offset": 2, + "slot": "4", + "type": "t_uint16" + }, + { + "astId": 19, + "contract": "contracts/HelloWorld.sol:HelloWorld", + "label": "offset3", + "offset": 4, + "slot": "4", + "type": "t_uint32" + }, + { + "astId": 21, + "contract": "contracts/HelloWorld.sol:HelloWorld", + "label": "offset4", + "offset": 8, + "slot": "4", + "type": "t_uint64" + }, + { + "astId": 23, + "contract": "contracts/HelloWorld.sol:HelloWorld", + "label": "offset5", + "offset": 16, + "slot": "4", + "type": "t_uint128" + } + ], + "types": { + "t_address": { + "encoding": "inplace", + "label": "address", + "numberOfBytes": "20" + }, + "t_bool": { + "encoding": "inplace", + "label": "bool", + "numberOfBytes": "1" + }, + "t_mapping(t_uint256,t_address)": { + "encoding": "mapping", + "key": "t_uint256", + "label": "mapping(uint256 => address)", + "numberOfBytes": "32", + "value": "t_address" + }, + "t_uint128": { + "encoding": "inplace", + "label": "uint128", + "numberOfBytes": "16" + }, + "t_uint16": { + "encoding": "inplace", + "label": "uint16", + "numberOfBytes": "2" + }, + "t_uint256": { + "encoding": "inplace", + "label": "uint256", + "numberOfBytes": "32" + }, + "t_uint32": { + "encoding": "inplace", + "label": "uint32", + "numberOfBytes": "4" + }, + "t_uint64": { + "encoding": "inplace", + "label": "uint64", + "numberOfBytes": "8" + }, + "t_uint8": { + "encoding": "inplace", + "label": "uint8", + "numberOfBytes": "1" + } + } +}