mirror of
https://github.com/ethereum/solidity
synced 2023-10-03 13:03:40 +00:00
Merge pull request #13533 from ethereum/evmhost-create
EVMHost: Calculate address for CREATE properly
This commit is contained in:
commit
2201526a90
@ -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<uint8_t>(value)};
|
||||
} else if (value <= 0xff) {
|
||||
return bytes{128 + 1, static_cast<uint8_t>(value)};
|
||||
} else if (value <= 0xffff) {
|
||||
return bytes{128 + 55 + 2, static_cast<uint8_t>(value >> 8), static_cast<uint8_t>(value)};
|
||||
} else {
|
||||
assertThrow(false, Exception, "Can only encode RLP numbers <= 0xffff");
|
||||
}
|
||||
};
|
||||
|
||||
bytes encodedNonce = encodeRlpInteger(sender.nonce);
|
||||
|
||||
h160 createAddress(keccak256(
|
||||
bytes{static_cast<uint8_t>(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 ||
|
||||
|
@ -19,4 +19,4 @@ contract C {
|
||||
// gas legacy: 250376
|
||||
// gas legacyOptimized: 174522
|
||||
// deposit(bytes32), 18 wei: 0x1234 ->
|
||||
// ~ emit Deposit(address,bytes32,uint256) from 0xf01f7809444bd9a93a854361c6fae3f23d9e23db: #0x0fdd67305928fcac8d213d1e47bfa6165cd0b87b, #0x1234, 0x00
|
||||
// ~ emit Deposit(address,bytes32,uint256) from 0x137aa4dfc0911524504fcd4d98501f179bc13b4a: #0xc06afe3a8444fc0004668591e8306bfb9968e79e, #0x1234, 0x00
|
||||
|
@ -6,4 +6,4 @@ contract C {
|
||||
}
|
||||
// ----
|
||||
// f() ->
|
||||
// ~ emit Test(function): #0x0fdd67305928fcac8d213d1e47bfa6165cd0b87b26121ff00000000000000000
|
||||
// ~ emit Test(function): #0xc06afe3a8444fc0004668591e8306bfb9968e79e26121ff00000000000000000
|
||||
|
@ -10,6 +10,6 @@ contract C {
|
||||
}
|
||||
// ----
|
||||
// f1() ->
|
||||
// ~ emit TestA(function): #0x0fdd67305928fcac8d213d1e47bfa6165cd0b87bc27fc3050000000000000000
|
||||
// ~ emit TestA(function): #0xc06afe3a8444fc0004668591e8306bfb9968e79ec27fc3050000000000000000
|
||||
// f2(uint256): 1 ->
|
||||
// ~ emit TestB(function): #0x0fdd67305928fcac8d213d1e47bfa6165cd0b87bbf3724af0000000000000000
|
||||
// ~ emit TestB(function): #0xc06afe3a8444fc0004668591e8306bfb9968e79ebf3724af0000000000000000
|
||||
|
@ -20,7 +20,7 @@ contract C {
|
||||
// gas irOptimized: 184005
|
||||
// gas legacy: 294335
|
||||
// gas legacyOptimized: 173427
|
||||
// f(uint256): 20 -> 1370859564726510389319704988634906228201275401179
|
||||
// f(uint256): 20 -> 0x137aa4dfc0911524504fcd4d98501f179bc13b4a
|
||||
// x() -> 1
|
||||
// f(uint256): 20 -> FAILURE
|
||||
// x() -> 1
|
||||
@ -29,5 +29,5 @@ contract C {
|
||||
// gas legacy: 483942
|
||||
// gas legacyOptimized: 302349
|
||||
// x() -> 1
|
||||
// stack(uint256): 10 -> 693016686122178122849713379390321835634789309880
|
||||
// stack(uint256): 10 -> 0x87948bd7ebbe13a00bfd930c93e4828ab18e3908
|
||||
// x() -> 2
|
||||
|
@ -9,4 +9,4 @@ contract C {
|
||||
// ====
|
||||
// compileToEwasm: also
|
||||
// ----
|
||||
// f() -> 90572315268751552425567948436632610904688605307, 90572315268751552425567948436632610904688605307
|
||||
// f() -> 0xc06afe3a8444fc0004668591e8306bfb9968e79e, 0xc06afe3a8444fc0004668591e8306bfb9968e79e
|
||||
|
@ -25,7 +25,7 @@ contract C {
|
||||
// increment() ->
|
||||
// y() -> 1
|
||||
// set() ->
|
||||
// x() -> 0xfdd67305928fcac8d213d1e47bfa6165cd0b87bd09de08a0000000000000000
|
||||
// x() -> 0xc06afe3a8444fc0004668591e8306bfb9968e79ed09de08a0000000000000000
|
||||
// increment() ->
|
||||
// y() -> 2
|
||||
// incrementIndirectly() ->
|
||||
|
@ -13,5 +13,5 @@ contract C {
|
||||
}
|
||||
}
|
||||
// ----
|
||||
// testYul() -> 0x0fdd67305928fcac8d213d1e47bfa6165cd0b87b
|
||||
// testSol() -> 0x0fdd67305928fcac8d213d1e47bfa6165cd0b87b
|
||||
// testYul() -> 0xc06afe3a8444fc0004668591e8306bfb9968e79e
|
||||
// testSol() -> 0xc06afe3a8444fc0004668591e8306bfb9968e79e
|
||||
|
@ -23,5 +23,5 @@ contract ClientReceipt {
|
||||
// gas irOptimized: 191881
|
||||
// gas legacy: 235167
|
||||
// gas legacyOptimized: 180756
|
||||
// getAddress() -> 0xf01f7809444bd9a93a854361c6fae3f23d9e23db
|
||||
// balance: 0xf01f7809444bd9a93a854361c6fae3f23d9e23db -> 500
|
||||
// getAddress() -> 0x137aa4dfc0911524504fcd4d98501f179bc13b4a
|
||||
// balance: 0x137aa4dfc0911524504fcd4d98501f179bc13b4a -> 500
|
||||
|
@ -0,0 +1,29 @@
|
||||
contract D {
|
||||
uint public x;
|
||||
constructor(uint a) {
|
||||
x = a;
|
||||
}
|
||||
}
|
||||
|
||||
contract C {
|
||||
function createDSalted(bytes32 salt, uint arg) public {
|
||||
address predictedAddress = address(uint160(uint(keccak256(abi.encodePacked(
|
||||
bytes1(0xff),
|
||||
address(this),
|
||||
salt,
|
||||
keccak256(abi.encodePacked(
|
||||
type(D).creationCode,
|
||||
arg
|
||||
))
|
||||
)))));
|
||||
|
||||
D d = new D{salt: salt}(arg);
|
||||
require(address(d) == predictedAddress, "Address mismatch.");
|
||||
}
|
||||
}
|
||||
// ====
|
||||
// EVMVersion: >=constantinople
|
||||
// compileViaYul: also
|
||||
// ----
|
||||
// createDSalted(bytes32,uint256): 42, 64 ->
|
||||
// gas legacy: 104365
|
@ -29,4 +29,4 @@ contract C {
|
||||
// EVMVersion: >=byzantium
|
||||
// ----
|
||||
// f() -> 0, 0, 96, 13, "test message."
|
||||
// g() -> 0xf01f7809444bd9a93a854361c6fae3f23d9e23db, 0, 96, 7, "success"
|
||||
// g() -> 0x137aa4dfc0911524504fcd4d98501f179bc13b4a, 0, 96, 7, "success"
|
||||
|
@ -14,4 +14,4 @@ contract C {
|
||||
function fun() public pure {}
|
||||
}
|
||||
// ----
|
||||
// f() -> 0x1, 0xfdd67305928fcac8d213d1e47bfa6165cd0b87b946644cd0000000000000000, 9
|
||||
// f() -> 0x1, 0xc06afe3a8444fc0004668591e8306bfb9968e79e946644cd0000000000000000, 9
|
||||
|
39
test/libsolidity/semanticTests/various/create_random.sol
Normal file
39
test/libsolidity/semanticTests/various/create_random.sol
Normal file
@ -0,0 +1,39 @@
|
||||
contract C {
|
||||
function addr() external returns (address) {
|
||||
return address(this);
|
||||
}
|
||||
|
||||
function testRunner() external returns (address a1, address a2) {
|
||||
assembly {
|
||||
// This is `return(0, 1)`. We are using a simplified/fixed initcode to avoid
|
||||
// instability due to metadata changes.
|
||||
let initcode := hex"60016000f3"
|
||||
mstore(0, initcode)
|
||||
|
||||
a1 := create(0, 0, 5)
|
||||
a2 := create2(0, 0, 5, address())
|
||||
}
|
||||
}
|
||||
|
||||
function testCalc() external returns (address a1, address a2) {
|
||||
a1 = calculateCreate(address(this), 1);
|
||||
a2 = calculateCreate2(address(this), keccak256(hex"60016000f3"), bytes32(uint256(uint160(address(this)))));
|
||||
}
|
||||
|
||||
function calculateCreate(address from, uint256 nonce) private pure returns (address) {
|
||||
assert(nonce <= 127);
|
||||
bytes memory data =
|
||||
bytes.concat(hex"d694", bytes20(uint160(from)), nonce == 0 ? bytes1(hex"80") : bytes1(uint8(nonce)));
|
||||
return address(uint160(uint256(keccak256(data)))); // Take the lower 160-bits
|
||||
}
|
||||
|
||||
function calculateCreate2(address creator, bytes32 codehash, bytes32 salt) private pure returns (address) {
|
||||
return address(uint160(uint256(keccak256(abi.encodePacked(bytes1(0xff), creator, salt, codehash)))));
|
||||
}
|
||||
}
|
||||
// ====
|
||||
// EVMVersion: >=constantinople
|
||||
// ----
|
||||
// addr() -> 0xc06afe3a8444fc0004668591e8306bfb9968e79e
|
||||
// testRunner() -> 0x137aa4dfc0911524504fcd4d98501f179bc13b4a, 0x2c1c30623ddd93e0b765a6caaca0c859eeb0644d
|
||||
// testCalc() -> 0x137aa4dfc0911524504fcd4d98501f179bc13b4a, 0x2c1c30623ddd93e0b765a6caaca0c859eeb0644d
|
@ -18,4 +18,4 @@ contract C {
|
||||
// ----
|
||||
// f(uint256): 2 -> 4
|
||||
// h(uint256): 2 -> 5
|
||||
// t() -> 0xFDD67305928FCAC8D213D1E47BFA6165CD0B87BB3DE648B0000000000000000, 0xFDD67305928FCAC8D213D1E47BFA6165CD0B87BB3DE648B0000000000000000
|
||||
// t() -> 0xc06afe3a8444fc0004668591e8306bfb9968e79eb3de648b0000000000000000, 0xc06afe3a8444fc0004668591e8306bfb9968e79eb3de648b0000000000000000
|
||||
|
@ -12,6 +12,6 @@ contract C {
|
||||
// ====
|
||||
// compileToEwasm: also
|
||||
// ----
|
||||
// f() -> 0x0fdd67305928fcac8d213d1e47bfa6165cd0b87b
|
||||
// f() -> 0xc06afe3a8444fc0004668591e8306bfb9968e79e
|
||||
// g() -> true
|
||||
// h(function): left(0x1122334400112233445566778899AABBCCDDEEFF42424242) -> 0x1122334400112233445566778899AABBCCDDEEFF
|
||||
|
Loading…
Reference in New Issue
Block a user