diff --git a/test/EVMHost.cpp b/test/EVMHost.cpp index d5ce8e605..7c9a8f4dd 100644 --- a/test/EVMHost.cpp +++ b/test/EVMHost.cpp @@ -250,23 +250,48 @@ evmc::result EVMHost::call(evmc_message const& _message) noexcept if (message.kind == EVMC_CREATE) { - // TODO this is not the right formula // TODO is the nonce incremented on failure, too? + // NOTE: nonce for creation from contracts starts at 1 + // TODO: check if sender is an EOA and do not pre-increment + sender.nonce++; + + auto encodeRlpInteger = [](int value) -> bytes { + if (value == 0) { + return bytes{128}; + } else if (value <= 127) { + return bytes{static_cast(value)}; + } else if (value <= 0xff) { + return bytes{128 + 1, static_cast(value)}; + } else if (value <= 0xffff) { + return bytes{128 + 55 + 2, static_cast(value >> 8), static_cast(value)}; + } else { + assertThrow(false, Exception, "Can only encode RLP numbers <= 0xffff"); + } + }; + + bytes encodedNonce = encodeRlpInteger(sender.nonce); + h160 createAddress(keccak256( + bytes{static_cast(0xc0 + 21 + encodedNonce.size())} + + bytes{0x94} + bytes(begin(message.sender.bytes), end(message.sender.bytes)) + - asBytes(to_string(sender.nonce++)) - ), h160::AlignLeft); + encodedNonce + ), h160::AlignRight); + message.destination = convertToEVMC(createAddress); + assertThrow(accounts.count(message.destination) == 0, Exception, "Account cannot exist"); + code = evmc::bytes(message.input_data, message.input_data + message.input_size); } else if (message.kind == EVMC_CREATE2) { h160 createAddress(keccak256( - bytes(1, 0xff) + + bytes{0xff} + bytes(begin(message.sender.bytes), end(message.sender.bytes)) + bytes(begin(message.create2_salt.bytes), end(message.create2_salt.bytes)) + keccak256(bytes(message.input_data, message.input_data + message.input_size)).asBytes() - ), h160::AlignLeft); + ), h160::AlignRight); + message.destination = convertToEVMC(createAddress); if (accounts.count(message.destination) && ( accounts[message.destination].nonce > 0 ||