@@ -497,6 +497,21 @@ static account_t *createNewAccount(account_t *from) {
497497 return result ;
498498}
499499
500+ // EIP-1014: keccak256(0xff ++ sender ++ salt ++ keccak256(initcode))[12:]
501+ static account_t * createNewAccount2 (account_t * from , const uint256_t * salt , const data_t * initcode ) {
502+ uint8_t inputBuffer [85 ];
503+ inputBuffer [0 ] = 0xff ;
504+ memcpy (inputBuffer + 1 , from -> address .address , 20 );
505+ dumpu256BE (salt , inputBuffer + 21 );
506+ keccak_256 (inputBuffer + 53 , 32 , initcode -> content , initcode -> size );
507+ addressHashResult_t hashResult ;
508+ keccak_256 ((uint8_t * )& hashResult , sizeof (hashResult ), inputBuffer , 85 );
509+ account_t * result = getAccount (hashResult .bottom160 );
510+ result -> nonce = 1 ;
511+ result -> warm = evmIteration ;
512+ return result ;
513+ }
514+
500515static account_t * warmAccount (context_t * callContext , const address_t address ) {
501516 account_t * account = getAccount (address );
502517 if (account -> warm != evmIteration ) {
@@ -680,6 +695,7 @@ static result_t evmStaticCall(address_t from, uint64_t gas, address_t to, data_t
680695static result_t evmDelegateCall (uint64_t gas , account_t * codeSource , data_t input );
681696static result_t evmCall (address_t from , uint64_t gas , address_t to , val_t value , data_t input );
682697static result_t evmCreate (account_t * fromAccount , uint64_t gas , val_t value , data_t input );
698+ static result_t evmCreate2 (account_t * fromAccount , uint64_t gas , val_t value , data_t input , const uint256_t * salt );
683699
684700static result_t doCall (context_t * callContext ) {
685701 if (SHOW_CALLS ) {
@@ -1526,6 +1542,47 @@ static result_t doCall(context_t *callContext) {
15261542 copy256 (callContext -> top - 1 , & createResult .status );
15271543 }
15281544 break ;
1545+ case CREATE2 :
1546+ {
1547+ data_t input ;
1548+ input .size = LOWER (LOWER_P (callContext -> top ));
1549+ uint64_t src = LOWER (LOWER_P (callContext -> top + 1 ));
1550+ if (!ensureMemory (callContext , src + input .size )) {
1551+ OUT_OF_GAS ;
1552+ }
1553+ input .content = callContext -> memory .uint8s + src ;
1554+ if (UPPER (UPPER_P (callContext -> top + 2 ))
1555+ || LOWER (UPPER_P (callContext -> top + 2 ))
1556+ || UPPER (LOWER_P (callContext -> top + 2 )) >> 32 ) {
1557+ callContext -> returnData .size = 0 ;
1558+ clear256 (callContext -> top - 1 );
1559+ break ;
1560+ }
1561+ val_t value ;
1562+ value [0 ] = UPPER (LOWER_P (callContext -> top + 2 ));
1563+ value [1 ] = LOWER (LOWER_P (callContext -> top + 2 )) >> 32 ;
1564+ value [2 ] = LOWER (LOWER_P (callContext -> top + 2 ));
1565+ const uint256_t * salt = callContext -> top - 1 ;
1566+
1567+ // apply R function before L function; CREATE2 adds keccak word cost
1568+ uint64_t rGas = initcodeGas (& input ) + G_KECCAK_WORD * ((input .size + 31 ) >> 5 );
1569+ if (callContext -> gas < rGas ) {
1570+ OUT_OF_GAS ;
1571+ }
1572+ callContext -> gas -= rGas ;
1573+ uint64_t gas = L (callContext -> gas );
1574+ callContext -> gas -= gas ;
1575+
1576+ result_t createResult = evmCreate2 (callContext -> account , gas , value , input , salt );
1577+ callContext -> gas += createResult .gasRemaining ;
1578+ mergeStateChanges (& result .stateChanges , createResult .stateChanges );
1579+ callContext -> returnData = createResult .returnData ;
1580+ if (!zero256 (& createResult .status )) {
1581+ callContext -> returnData .size = 0 ; // EIP-211: success = empty buffer
1582+ }
1583+ copy256 (callContext -> top - 1 , & createResult .status );
1584+ }
1585+ break ;
15291586 case CALL :
15301587 {
15311588 data_t input ;
@@ -1967,6 +2024,22 @@ result_t evmCreate(account_t *fromAccount, uint64_t gas, val_t value, data_t inp
19672024 return _evmConstruct (fromAccount -> address , createNewAccount (fromAccount ), gas , value , input );
19682025}
19692026
2027+ static result_t evmCreate2 (account_t * fromAccount , uint64_t gas , val_t value , data_t input , const uint256_t * salt ) {
2028+ if (!BalanceSub (fromAccount -> balance , value )) {
2029+ fprintf (stderr , "Insufficient balance [0x%08x%08x%08x] for create2 (need [0x%08x%08x%08x])\n" ,
2030+ fromAccount -> balance [0 ], fromAccount -> balance [1 ], fromAccount -> balance [2 ],
2031+ value [0 ], value [1 ], value [2 ]
2032+ );
2033+ result_t result ;
2034+ result .gasRemaining = gas ;
2035+ result .stateChanges = NULL ;
2036+ clear256 (& result .status );
2037+ result .returnData .size = 0 ;
2038+ return result ;
2039+ }
2040+ return _evmConstruct (fromAccount -> address , createNewAccount2 (fromAccount , salt , & input ), gas , value , input );
2041+ }
2042+
19702043result_t txCreate (address_t from , uint64_t gas , val_t value , data_t input ) {
19712044 account_t * fromAccount = getAccount (from );
19722045 fromAccount -> warm = evmIteration ;
0 commit comments