Skip to content
This repository was archived by the owner on Jan 5, 2019. It is now read-only.

Commit d18630c

Browse files
committed
Basic support for STATICCALL
1 parent 1a93923 commit d18630c

File tree

6 files changed

+24
-3
lines changed

6 files changed

+24
-3
lines changed

include/evm2wasm.h

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -74,6 +74,7 @@ enum class opcodeEnum
7474
CALLCODE,
7575
RETURN,
7676
DELEGATECALL,
77+
STATICCALL,
7778
SELFDESTRUCT,
7879
INVALID,
7980
bswap_i32,
@@ -266,6 +267,7 @@ static std::map<int, std::tuple<opcodeEnum, int, int, int>> codes = {
266267
{0xf2, Opcode{opcodeEnum::CALLCODE, 0, 7, 1}},
267268
{0xf3, Opcode{opcodeEnum::RETURN, 0, 2, 0}},
268269
{0xf4, Opcode{opcodeEnum::DELEGATECALL, 0, 6, 1}},
270+
{0xfa, Opcode{opcodeEnum::STATICCALL, 0, 6, 1}},
269271

270272
// "0x70", range - other
271273
{0xff, Opcode{opcodeEnum::SELFDESTRUCT, 0, 1, 0}}};
@@ -318,6 +320,9 @@ static std::map<opcodeEnum, std::vector<opcodeEnum>> depMap = {
318320
{opcodeEnum::bswap_m256, opcodeEnum::callback, opcodeEnum::memusegas,
319321
opcodeEnum::check_overflow, opcodeEnum::memset, opcodeEnum::callback_32,
320322
opcodeEnum::check_overflow_i64}},
323+
{opcodeEnum::STATICCALL, {opcodeEnum::callback, opcodeEnum::memusegas,
324+
opcodeEnum::check_overflow, opcodeEnum::memset,
325+
opcodeEnum::check_overflow_i64, opcodeEnum::callback_32}},
321326
{opcodeEnum::CREATE, {opcodeEnum::bswap_m256, opcodeEnum::bswap_m160, opcodeEnum::callback_160,
322327
opcodeEnum::memusegas, opcodeEnum::check_overflow}},
323328
{opcodeEnum::RETURN, {opcodeEnum::memusegas, opcodeEnum::check_overflow}},

index.js

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -39,6 +39,7 @@ const depMap = new Map([
3939
['SHA3', ['memusegas', 'bswap_m256', 'check_overflow', 'keccak']],
4040
['CALL', ['bswap_m256', 'memusegas', 'check_overflow_i64', 'check_overflow', 'memset', 'callback_32']],
4141
['DELEGATECALL', ['callback', 'memusegas', 'check_overflow_i64', 'check_overflow', 'memset', 'callback_32']],
42+
['STATICCALL', ['callback', 'memusegas', 'check_overflow_i64', 'check_overflow', 'memset', 'callback_32']],
4243
['CALLCODE', ['bswap_m256', 'callback', 'memusegas', 'check_overflow_i64', 'check_overflow', 'check_overflow_i64', 'memset', 'callback_32']],
4344
['CREATE', ['bswap_m256', 'bswap_m160', 'callback_160', 'memusegas', 'check_overflow']],
4445
['RETURN', ['memusegas', 'check_overflow']],

opcodes.js

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -147,6 +147,7 @@ const codes = {
147147
0xf2: ['CALLCODE', 0, 7, 1],
148148
0xf3: ['RETURN', 0, 2, 0],
149149
0xf4: ['DELEGATECALL', 0, 6, 1],
150+
0xfa: ['STATICCALL', 0, 6, 1],
150151

151152
// '0x70', range - other
152153
0xff: ['SELFDESTRUCT', 0, 1, 0]

wasm/generateInterface.js

Lines changed: 9 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -155,6 +155,12 @@ const interfaceManifest = {
155155
input: ['gasLimit', 'address', 'i128', 'readOffset', 'length'],
156156
output: ['i32']
157157
},
158+
STATICCALL: {
159+
name: 'callStatic',
160+
async: true,
161+
input: ['gasLimit', 'address', 'readOffset', 'length'],
162+
output: ['i32']
163+
},
158164
SSTORE: {
159165
name: 'storageStore',
160166
async: true,
@@ -289,7 +295,7 @@ function generateManifest (interfaceManifest, opts) {
289295
locals += `(local $offset${numOfLocals} i32)`
290296
body += `(set_local $offset${numOfLocals} ${checkOverflowStackItem256(spOffset)})`
291297
call += `(get_local $offset${numOfLocals})`
292-
} else if (input === 'length' && (opcode === 'CALL' || opcode === 'CALLCODE' || opcode === 'DELEGATECALL')) {
298+
} else if (input === 'length' && (opcode === 'CALL' || opcode === 'CALLCODE' || opcode === 'DELEGATECALL' || opcode === 'STATICCALL')) {
293299
// CALLs in EVM have 7 arguments
294300
// but in ewasm CALLs only have 5 arguments
295301
// so delete the bottom two stack elements, after processing the 5th argument
@@ -309,7 +315,7 @@ function generateManifest (interfaceManifest, opts) {
309315

310316
// delete 7th stack element
311317
spOffset--
312-
} else if (input === 'length' && (opcode !== 'CALL' && opcode !== 'CALLCODE' && opcode !== 'DELEGATECALL')) {
318+
} else if (input === 'length' && (opcode !== 'CALL' && opcode !== 'CALLCODE' && opcode !== 'DELEGATECALL' && opcode !== 'STATICCALL')) {
313319
locals += `(local $length${numOfLocals} i32)`
314320
body += `(set_local $length${numOfLocals} ${checkOverflowStackItem256(spOffset)})`
315321

@@ -368,7 +374,7 @@ function generateManifest (interfaceManifest, opts) {
368374
call += '(get_local $callback)'
369375
}
370376

371-
if (opcode === 'CALL' || opcode === 'CALLCODE' || opcode === 'DELEGATECALL') {
377+
if (opcode === 'CALL' || opcode === 'CALLCODE' || opcode === 'DELEGATECALL' || opcode === 'STATICCALL') {
372378
call =
373379
`(i64.store
374380
(i32.add (get_global $sp) (i32.const ${spOffset * 32}))

wasm/wast-async.json

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -99,6 +99,10 @@
9999
"wast": ";; generated by ./wasm/generateInterface.js\n(func $DELEGATECALL (param $callback i32)(local $offset0 i32)(local $length0 i32)(local $offset1 i32)(local $length1 i32) (set_local $offset0 (call $check_overflow\n (i64.load (i32.add (get_global $sp) (i32.const -96)))\n (i64.load (i32.add (get_global $sp) (i32.const -88)))\n (i64.load (i32.add (get_global $sp) (i32.const -80)))\n (i64.load (i32.add (get_global $sp) (i32.const -72)))))(set_local $length0 (call $check_overflow\n (i64.load (i32.add (get_global $sp) (i32.const -128)))\n (i64.load (i32.add (get_global $sp) (i32.const -120)))\n (i64.load (i32.add (get_global $sp) (i32.const -112)))\n (i64.load (i32.add (get_global $sp) (i32.const -104)))))\n (call $memusegas (get_local $offset0) (get_local $length0))\n (set_local $offset0 (i32.add (get_global $memstart) (get_local $offset0)))(set_local $offset1 (call $check_overflow\n (i64.load (i32.add (get_global $sp) (i32.const -160)))\n (i64.load (i32.add (get_global $sp) (i32.const -152)))\n (i64.load (i32.add (get_global $sp) (i32.const -144)))\n (i64.load (i32.add (get_global $sp) (i32.const -136)))))(set_local $length1 (call $check_overflow\n (i64.load (i32.add (get_global $sp) (i32.const -192)))\n (i64.load (i32.add (get_global $sp) (i32.const -184)))\n (i64.load (i32.add (get_global $sp) (i32.const -176)))\n (i64.load (i32.add (get_global $sp) (i32.const -168)))))\n (call $memusegas (get_local $offset1) (get_local $length1))\n (set_local $offset1 (i32.add (get_global $memstart) (get_local $offset1))) (i64.store\n (i32.add (get_global $sp) (i32.const -192))\n (i64.extend_u/i32\n (i32.eqz (call $callDelegate(call $check_overflow_i64\n (i64.load (i32.add (get_global $sp) (i32.const 0)))\n (i64.load (i32.add (get_global $sp) (i32.const 8)))\n (i64.load (i32.add (get_global $sp) (i32.const 16)))\n (i64.load (i32.add (get_global $sp) (i32.const 24))))(i32.add (get_global $sp) (i32.const -32))(i32.add (get_global $sp) (i32.const -64))(get_local $offset0)(get_local $length0)(get_local $offset1)(get_local $length1)(get_local $callback)) ;; flip CALL result from EEI to EVM convention (0 -> 1, 1,2,.. -> 1)\n )))\n ;; zero out mem\n (i64.store (i32.add (get_global $sp) (i32.const -168)) (i64.const 0))\n (i64.store (i32.add (get_global $sp) (i32.const -176)) (i64.const 0))\n (i64.store (i32.add (get_global $sp) (i32.const -184)) (i64.const 0)))",
100100
"imports": "(import \"ethereum\" \"callDelegate\" (func $callDelegate (param i64 i32 i32 i32 i32 i32 i32 i32) (result i32)))"
101101
},
102+
"STATICCALL": {
103+
"wast": ";; generated by ./wasm/generateInterface.js\n(func $STATICCALL (param $callback i32)(local $offset0 i32)(local $length0 i32) (set_local $offset0 \n (call $check_overflow\n (i64.load (i32.add (get_global $sp) (i32.const -64)))\n (i64.load (i32.add (get_global $sp) (i32.const -56)))\n (i64.load (i32.add (get_global $sp) (i32.const -48)))\n (i64.load (i32.add (get_global $sp) (i32.const -40)))))(set_local $length0 \n (call $check_overflow \n (i64.load (i32.add (get_global $sp) (i32.const -96)))\n (i64.load (i32.add (get_global $sp) (i32.const -88)))\n (i64.load (i32.add (get_global $sp) (i32.const -80)))\n (i64.load (i32.add (get_global $sp) (i32.const -72)))))\n\n (call $memusegas (get_local $offset0) (get_local $length0))\n (set_local $offset0 (i32.add (get_global $memstart) (get_local $offset0))) (i64.store\n (i32.add (get_global $sp) (i32.const -160))\n (i64.extend_u/i32\n (i32.eqz (call $callStatic(call $check_overflow_i64\n (i64.load (i32.add (get_global $sp) (i32.const 0)))\n (i64.load (i32.add (get_global $sp) (i32.const 8)))\n (i64.load (i32.add (get_global $sp) (i32.const 16)))\n (i64.load (i32.add (get_global $sp) (i32.const 24))))(i32.add (get_global $sp) (i32.const -32))(get_local $offset0)(get_local $length0)\n ;; zero out mem\n (i64.store (i32.add (get_global $sp) (i32.const -96)) (i64.const 0))\n (i64.store (i32.add (get_global $sp) (i32.const -104)) (i64.const 0))\n (i64.store (i32.add (get_global $sp) (i32.const -112)) (i64.const 0))\n (i64.store (i32.add (get_global $sp) (i32.const -120)) (i64.const 0))\n ;; zero out mem\n (i64.store (i32.add (get_global $sp) (i32.const -128)) (i64.const 0))\n (i64.store (i32.add (get_global $sp) (i32.const -136)) (i64.const 0))\n (i64.store (i32.add (get_global $sp) (i32.const -144)) (i64.const 0))\n (i64.store (i32.add (get_global $sp) (i32.const -152)) (i64.const 0))(get_local $callback)) ;; flip CALL result from EEI to EVM convention (0 -> 1, 1,2,.. -> 1)\n )))\n ;; zero out mem\n (i64.store (i32.add (get_global $sp) (i32.const -136)) (i64.const 0))\n (i64.store (i32.add (get_global $sp) (i32.const -144)) (i64.const 0))\n (i64.store (i32.add (get_global $sp) (i32.const -152)) (i64.const 0)))",
104+
"imports": "(import \"ethereum\" \"callStatic\" (func $callStatic (param i64 i32 i32 i32 i32) (result i32)))"
105+
},
102106
"SSTORE": {
103107
"wast": ";; generated by ./wasm/generateInterface.js\n(func $SSTORE (param $callback i32) (call $storageStore(get_global $sp)(i32.add (get_global $sp) (i32.const -32))(get_local $callback)))",
104108
"imports": "(import \"ethereum\" \"storageStore\" (func $storageStore (param i32 i32 i32) ))"

wasm/wast.json

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -99,6 +99,10 @@
9999
"wast": ";; generated by ./wasm/generateInterface.js\n(func $DELEGATECALL (local $offset0 i32)(local $length0 i32)(local $offset1 i32)(local $length1 i32) (set_local $offset0 (call $check_overflow\n (i64.load (i32.add (get_global $sp) (i32.const -96)))\n (i64.load (i32.add (get_global $sp) (i32.const -88)))\n (i64.load (i32.add (get_global $sp) (i32.const -80)))\n (i64.load (i32.add (get_global $sp) (i32.const -72)))))(set_local $length0 (call $check_overflow\n (i64.load (i32.add (get_global $sp) (i32.const -128)))\n (i64.load (i32.add (get_global $sp) (i32.const -120)))\n (i64.load (i32.add (get_global $sp) (i32.const -112)))\n (i64.load (i32.add (get_global $sp) (i32.const -104)))))\n (call $memusegas (get_local $offset0) (get_local $length0))\n (set_local $offset0 (i32.add (get_global $memstart) (get_local $offset0)))(set_local $offset1 (call $check_overflow\n (i64.load (i32.add (get_global $sp) (i32.const -160)))\n (i64.load (i32.add (get_global $sp) (i32.const -152)))\n (i64.load (i32.add (get_global $sp) (i32.const -144)))\n (i64.load (i32.add (get_global $sp) (i32.const -136)))))(set_local $length1 (call $check_overflow\n (i64.load (i32.add (get_global $sp) (i32.const -192)))\n (i64.load (i32.add (get_global $sp) (i32.const -184)))\n (i64.load (i32.add (get_global $sp) (i32.const -176)))\n (i64.load (i32.add (get_global $sp) (i32.const -168)))))\n (call $memusegas (get_local $offset1) (get_local $length1))\n (set_local $offset1 (i32.add (get_global $memstart) (get_local $offset1))) (i64.store\n (i32.add (get_global $sp) (i32.const -192))\n (i64.extend_u/i32\n (i32.eqz (call $callDelegate(call $check_overflow_i64\n (i64.load (i32.add (get_global $sp) (i32.const 0)))\n (i64.load (i32.add (get_global $sp) (i32.const 8)))\n (i64.load (i32.add (get_global $sp) (i32.const 16)))\n (i64.load (i32.add (get_global $sp) (i32.const 24))))(i32.add (get_global $sp) (i32.const -32))(i32.add (get_global $sp) (i32.const -64))(get_local $offset0)(get_local $length0)(get_local $offset1)(get_local $length1)) ;; flip CALL result from EEI to EVM convention (0 -> 1, 1,2,.. -> 1)\n )))\n ;; zero out mem\n (i64.store (i32.add (get_global $sp) (i32.const -168)) (i64.const 0))\n (i64.store (i32.add (get_global $sp) (i32.const -176)) (i64.const 0))\n (i64.store (i32.add (get_global $sp) (i32.const -184)) (i64.const 0)))",
100100
"imports": "(import \"ethereum\" \"callDelegate\" (func $callDelegate (param i64 i32 i32 i32 i32 i32 i32) (result i32)))"
101101
},
102+
"STATICCALL": {
103+
"wast": ";; generated by ./wasm/generateInterface.js\n(func $STATICCALL (local $offset0 i32)(local $length0 i32) (set_local $offset0 \n (call $check_overflow\n (i64.load (i32.add (get_global $sp) (i32.const -64)))\n (i64.load (i32.add (get_global $sp) (i32.const -56)))\n (i64.load (i32.add (get_global $sp) (i32.const -48)))\n (i64.load (i32.add (get_global $sp) (i32.const -40)))))(set_local $length0 \n (call $check_overflow \n (i64.load (i32.add (get_global $sp) (i32.const -96)))\n (i64.load (i32.add (get_global $sp) (i32.const -88)))\n (i64.load (i32.add (get_global $sp) (i32.const -80)))\n (i64.load (i32.add (get_global $sp) (i32.const -72)))))\n\n (call $memusegas (get_local $offset0) (get_local $length0))\n (set_local $offset0 (i32.add (get_global $memstart) (get_local $offset0))) (i64.store\n (i32.add (get_global $sp) (i32.const -160))\n (i64.extend_u/i32\n (i32.eqz (call $callStatic(call $check_overflow_i64\n (i64.load (i32.add (get_global $sp) (i32.const 0)))\n (i64.load (i32.add (get_global $sp) (i32.const 8)))\n (i64.load (i32.add (get_global $sp) (i32.const 16)))\n (i64.load (i32.add (get_global $sp) (i32.const 24))))(i32.add (get_global $sp) (i32.const -32))(get_local $offset0)(get_local $length0)\n ;; zero out mem\n (i64.store (i32.add (get_global $sp) (i32.const -96)) (i64.const 0))\n (i64.store (i32.add (get_global $sp) (i32.const -104)) (i64.const 0))\n (i64.store (i32.add (get_global $sp) (i32.const -112)) (i64.const 0))\n (i64.store (i32.add (get_global $sp) (i32.const -120)) (i64.const 0))\n ;; zero out mem\n (i64.store (i32.add (get_global $sp) (i32.const -128)) (i64.const 0))\n (i64.store (i32.add (get_global $sp) (i32.const -136)) (i64.const 0))\n (i64.store (i32.add (get_global $sp) (i32.const -144)) (i64.const 0))\n (i64.store (i32.add (get_global $sp) (i32.const -152)) (i64.const 0))) ;; flip CALL result from EEI to EVM convention (0 -> 1, 1,2,.. -> 1)\n )))\n ;; zero out mem\n (i64.store (i32.add (get_global $sp) (i32.const -136)) (i64.const 0))\n (i64.store (i32.add (get_global $sp) (i32.const -144)) (i64.const 0))\n (i64.store (i32.add (get_global $sp) (i32.const -152)) (i64.const 0)))",
104+
"imports": "(import \"ethereum\" \"callStatic\" (func $callStatic (param i64 i32 i32 i32) (result i32)))"
105+
},
102106
"SSTORE": {
103107
"wast": ";; generated by ./wasm/generateInterface.js\n(func $SSTORE (call $storageStore(get_global $sp)(i32.add (get_global $sp) (i32.const -32))))",
104108
"imports": "(import \"ethereum\" \"storageStore\" (func $storageStore (param i32 i32) ))"

0 commit comments

Comments
 (0)