Skip to content

Commit a71d069

Browse files
committed
Fix merge conflict
2 parents 388a037 + d4cff4f commit a71d069

File tree

7 files changed

+98
-26
lines changed

7 files changed

+98
-26
lines changed

lib/evm/eei.ts

+7
Original file line numberDiff line numberDiff line change
@@ -115,6 +115,13 @@ export default class EEI {
115115
return new BN(account.balance)
116116
}
117117

118+
/**
119+
* Returns balance of self.
120+
*/
121+
getSelfBalance(): BN {
122+
return new BN(this._env.contract.balance)
123+
}
124+
118125
/**
119126
* Returns caller address. This is the address of the account
120127
* that is directly responsible for this execution.

lib/evm/opFns.ts

+7
Original file line numberDiff line numberDiff line change
@@ -463,6 +463,13 @@ export const handlers: { [k: string]: OpHandler } = {
463463

464464
runState.stack.push(runState.eei.getChainId())
465465
},
466+
SELFBALANCE: function(runState: RunState) {
467+
if (!runState._common.gteHardfork('istanbul')) {
468+
trap(ERROR.INVALID_OPCODE)
469+
}
470+
471+
runState.stack.push(runState.eei.getSelfBalance())
472+
},
466473
// 0x50 range - 'storage' and execution
467474
POP: function(runState: RunState) {
468475
runState.stack.pop()

lib/evm/opcodes.ts

+32-21
Original file line numberDiff line numberDiff line change
@@ -2,13 +2,12 @@ export interface OpInfo {
22
name: string
33
opcode: number
44
fee: number
5-
dynamic: boolean
65
isAsync: boolean
76
}
87

9-
const codes: any = {
8+
let codes: any = {
109
// 0x0 range - arithmetic ops
11-
// name, baseCost, dynamic, async
10+
// name, baseCost, async
1211
0x00: ['STOP', 0, false],
1312
0x01: ['ADD', 3, false],
1413
0x02: ['MUL', 5, false],
@@ -43,7 +42,7 @@ const codes: any = {
4342

4443
// 0x30 range - closure state
4544
0x30: ['ADDRESS', 2, true],
46-
0x31: ['BALANCE', 400, true, true],
45+
0x31: ['BALANCE', 400, true],
4746
0x32: ['ORIGIN', 2, true],
4847
0x33: ['CALLER', 2, true],
4948
0x34: ['CALLVALUE', 2, true],
@@ -53,28 +52,27 @@ const codes: any = {
5352
0x38: ['CODESIZE', 2, false],
5453
0x39: ['CODECOPY', 3, false],
5554
0x3a: ['GASPRICE', 2, false],
56-
0x3b: ['EXTCODESIZE', 700, true, true],
57-
0x3c: ['EXTCODECOPY', 700, true, true],
55+
0x3b: ['EXTCODESIZE', 700, true],
56+
0x3c: ['EXTCODECOPY', 700, true],
5857
0x3d: ['RETURNDATASIZE', 2, true],
5958
0x3e: ['RETURNDATACOPY', 3, true],
60-
0x3f: ['EXTCODEHASH', 400, true, true],
59+
0x3f: ['EXTCODEHASH', 400, true],
6160

6261
// '0x40' range - block operations
63-
0x40: ['BLOCKHASH', 20, true, true],
62+
0x40: ['BLOCKHASH', 20, true],
6463
0x41: ['COINBASE', 2, true],
6564
0x42: ['TIMESTAMP', 2, true],
6665
0x43: ['NUMBER', 2, true],
6766
0x44: ['DIFFICULTY', 2, true],
6867
0x45: ['GASLIMIT', 2, true],
69-
0x46: ['CHAINID', 2, false],
7068

7169
// 0x50 range - 'storage' and execution
7270
0x50: ['POP', 2, false],
7371
0x51: ['MLOAD', 3, false],
7472
0x52: ['MSTORE', 3, false],
7573
0x53: ['MSTORE8', 3, false],
76-
0x54: ['SLOAD', 200, true, true],
77-
0x55: ['SSTORE', 0, true, true],
74+
0x54: ['SLOAD', 200, true],
75+
0x55: ['SSTORE', 0, true],
7876
0x56: ['JUMP', 8, false],
7977
0x57: ['JUMPI', 10, false],
8078
0x58: ['PC', 2, false],
@@ -157,22 +155,36 @@ const codes: any = {
157155
0xa4: ['LOG', 375, false],
158156

159157
// '0xf0' range - closures
160-
0xf0: ['CREATE', 32000, true, true],
161-
0xf1: ['CALL', 700, true, true],
162-
0xf2: ['CALLCODE', 700, true, true],
158+
0xf0: ['CREATE', 32000, true],
159+
0xf1: ['CALL', 700, true],
160+
0xf2: ['CALLCODE', 700, true],
163161
0xf3: ['RETURN', 0, false],
164-
0xf4: ['DELEGATECALL', 700, true, true],
165-
0xf5: ['CREATE2', 32000, true, true],
166-
0xfa: ['STATICCALL', 700, true, true],
162+
0xf4: ['DELEGATECALL', 700, true],
163+
0xf5: ['CREATE2', 32000, true],
164+
0xfa: ['STATICCALL', 700, true],
167165
0xfd: ['REVERT', 0, false],
168166

169167
// '0x70', range - other
170168
0xfe: ['INVALID', 0, false],
171-
0xff: ['SELFDESTRUCT', 5000, false, true],
169+
0xff: ['SELFDESTRUCT', 5000, true],
170+
}
171+
172+
const istanbulOpcodes: any = {
173+
0x31: ['BALANCE', 700, true],
174+
0x3f: ['EXTCODEHASH', 700, true],
175+
0x46: ['CHAINID', 2, false],
176+
0x47: ['SELFBALANCE', 5, false],
177+
0x54: ['SLOAD', 800, true],
178+
}
179+
180+
export function setOpcodes(hf: string) {
181+
if (hf === 'istanbul') {
182+
codes = { ...codes, ...istanbulOpcodes }
183+
}
172184
}
173185

174186
export function lookupOpInfo(op: number, full: boolean = false): OpInfo {
175-
const code = codes[op] ? codes[op] : ['INVALID', 0, false, false]
187+
const code = codes[op] ? codes[op] : ['INVALID', 0, false]
176188
let opcode = code[0]
177189

178190
if (full) {
@@ -197,7 +209,6 @@ export function lookupOpInfo(op: number, full: boolean = false): OpInfo {
197209
name: opcode,
198210
opcode: op,
199211
fee: code[1],
200-
dynamic: code[2],
201-
isAsync: code[3],
212+
isAsync: code[2],
202213
}
203214
}

lib/index.ts

+4
Original file line numberDiff line numberDiff line change
@@ -8,6 +8,7 @@ import { default as runCall, RunCallOpts } from './runCall'
88
import { default as runTx, RunTxOpts, RunTxResult } from './runTx'
99
import { default as runBlock, RunBlockOpts, RunBlockResult } from './runBlock'
1010
import { EVMResult, ExecResult } from './evm/evm'
11+
import { setOpcodes } from './evm/opcodes'
1112
import runBlockchain from './runBlockchain'
1213
const promisify = require('util.promisify')
1314
const AsyncEventEmitter = require('async-eventemitter')
@@ -109,6 +110,9 @@ export default class VM extends AsyncEventEmitter {
109110

110111
this.allowUnlimitedContractSize =
111112
opts.allowUnlimitedContractSize === undefined ? false : opts.allowUnlimitedContractSize
113+
114+
// Set list of opcodes based on HF
115+
setOpcodes(this._common.hardfork()!)
112116
}
113117

114118
/**

lib/runTx.ts

+3-4
Original file line numberDiff line numberDiff line change
@@ -114,15 +114,14 @@ async function _runTx(this: VM, opts: RunTxOpts): Promise<RunTxResult> {
114114
throw new Error(
115115
`sender doesn't have enough funds to send tx. The upfront cost is: ${tx
116116
.getUpfrontCost()
117-
.toString()}\
118-
and the sender's account only has: ${new BN(fromAccount.balance).toString()}`,
117+
.toString()}` +
118+
` and the sender's account only has: ${new BN(fromAccount.balance).toString()}`,
119119
)
120120
} else if (!opts.skipNonce && !new BN(fromAccount.nonce).eq(new BN(tx.nonce))) {
121121
throw new Error(
122122
`the tx doesn't have the correct nonce. account has nonce of: ${new BN(
123123
fromAccount.nonce,
124-
).toString()}\
125-
tx has nonce of: ${new BN(tx.nonce).toString()}`,
124+
).toString()} tx has nonce of: ${new BN(tx.nonce).toString()}`,
126125
)
127126
}
128127
// Update from account's nonce and balance

package.json

+1-1
Original file line numberDiff line numberDiff line change
@@ -54,7 +54,7 @@
5454
"ethereumjs-block": "~2.2.0",
5555
"ethereumjs-blockchain": "^4.0.1",
5656
"ethereumjs-common": "^1.3.1",
57-
"ethereumjs-tx": "^2.1.0",
57+
"ethereumjs-tx": "^2.1.1",
5858
"ethereumjs-util": "^6.1.0",
5959
"fake-merkle-patricia-tree": "^1.0.1",
6060
"functional-red-black-tree": "^1.0.1",

tests/api/istanbul/eip-1884.js

+44
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,44 @@
1+
const tape = require('tape')
2+
const BN = require('bn.js')
3+
const Common = require('ethereumjs-common').default
4+
const VM = require('../../../dist/index').default
5+
const PStateManager = require('../../../dist/state/promisified').default
6+
const { ERROR } = require('../../../dist/exceptions')
7+
const { createAccount } = require('../utils')
8+
9+
const testCases = [
10+
{ chain: 'mainnet', hardfork: 'istanbul', selfbalance: '0xf1' },
11+
{ chain: 'mainnet', hardfork: 'constantinople', err: ERROR.INVALID_OPCODE }
12+
]
13+
14+
// SELFBALANCE PUSH8 0x00 MSTORE8 PUSH8 0x01 PUSH8 0x00 RETURN
15+
const code = ['47', '60', '00', '53', '60', '01', '60', '00', 'f3']
16+
tape('Istanbul: EIP-1884: SELFBALANCE', async (t) => {
17+
const addr = Buffer.from('00000000000000000000000000000000000000ff', 'hex')
18+
const runCodeArgs = {
19+
code: Buffer.from(code.join(''), 'hex'),
20+
gasLimit: new BN(0xffff),
21+
address: addr
22+
}
23+
24+
for (const testCase of testCases) {
25+
const common = new Common(testCase.chain, testCase.hardfork)
26+
const vm = new VM({ common })
27+
const state = new PStateManager(vm.stateManager)
28+
const account = createAccount('00', testCase.selfbalance)
29+
await state.putAccount(addr, account)
30+
try {
31+
const res = await vm.runCode(runCodeArgs)
32+
if (testCase.err) {
33+
t.equal(res.exceptionError.error, testCase.err)
34+
} else {
35+
t.assert(res.exceptionError === undefined)
36+
t.assert(new BN(Buffer.from(testCase.selfbalance.slice(2), 'hex')).eq(new BN(res.returnValue)))
37+
}
38+
} catch (e) {
39+
t.fail(e.message)
40+
}
41+
}
42+
43+
t.end()
44+
})

0 commit comments

Comments
 (0)