From 135a0aaa64f4fcf2c0d08ad709ad517254e42095 Mon Sep 17 00:00:00 2001 From: Kelvin Fichter Date: Sat, 24 Apr 2021 00:28:11 -0400 Subject: [PATCH] feat[contracts]: Limit nonce and gasLimit to uint64 --- .../OVM/execution/OVM_ExecutionManager.sol | 8 ++-- .../OVM/execution/OVM_StateManager.sol | 4 +- .../iOVM/execution/iOVM_ExecutionManager.sol | 2 +- .../iOVM/execution/iOVM_StateManager.sol | 4 +- .../libraries/codec/Lib_EIP155Tx.sol | 8 ++-- .../libraries/codec/Lib_OVMCodec.sol | 8 ++-- .../libraries/rlp/Lib_RLPReader.sol | 41 +++++++++++++++++++ .../accounts/OVM_ECDSAContractAccount.spec.ts | 1 - .../OVM_ExecutionManager/nuisance-gas.spec.ts | 2 +- 9 files changed, 59 insertions(+), 19 deletions(-) diff --git a/packages/contracts/contracts/optimistic-ethereum/OVM/execution/OVM_ExecutionManager.sol b/packages/contracts/contracts/optimistic-ethereum/OVM/execution/OVM_ExecutionManager.sol index 546f0fa5f0291..4693d5f46547b 100644 --- a/packages/contracts/contracts/optimistic-ethereum/OVM/execution/OVM_ExecutionManager.sol +++ b/packages/contracts/contracts/optimistic-ethereum/OVM/execution/OVM_ExecutionManager.sol @@ -458,7 +458,7 @@ contract OVM_ExecutionManager is iOVM_ExecutionManager, Lib_AddressResolver { override public returns ( - uint256 _nonce + uint64 _nonce ) { return _getAccountNonce(ovmADDRESS()); @@ -473,7 +473,7 @@ contract OVM_ExecutionManager is iOVM_ExecutionManager, Lib_AddressResolver { notStatic { address account = ovmADDRESS(); - uint256 nonce = _getAccountNonce(account); + uint64 nonce = _getAccountNonce(account); // Prevent overflow. if (nonce + 1 > nonce) { @@ -1181,7 +1181,7 @@ contract OVM_ExecutionManager is iOVM_ExecutionManager, Lib_AddressResolver { */ function _setAccountNonce( address _address, - uint256 _nonce + uint64 _nonce ) internal { @@ -1199,7 +1199,7 @@ contract OVM_ExecutionManager is iOVM_ExecutionManager, Lib_AddressResolver { ) internal returns ( - uint256 _nonce + uint64 _nonce ) { _checkAccountLoad(_address); diff --git a/packages/contracts/contracts/optimistic-ethereum/OVM/execution/OVM_StateManager.sol b/packages/contracts/contracts/optimistic-ethereum/OVM/execution/OVM_StateManager.sol index 2d8a95bc13e6b..0f08a30d976b7 100644 --- a/packages/contracts/contracts/optimistic-ethereum/OVM/execution/OVM_StateManager.sol +++ b/packages/contracts/contracts/optimistic-ethereum/OVM/execution/OVM_StateManager.sol @@ -207,7 +207,7 @@ contract OVM_StateManager is iOVM_StateManager { */ function setAccountNonce( address _address, - uint256 _nonce + uint64 _nonce ) override public @@ -228,7 +228,7 @@ contract OVM_StateManager is iOVM_StateManager { public view returns ( - uint256 + uint64 ) { return accounts[_address].nonce; diff --git a/packages/contracts/contracts/optimistic-ethereum/iOVM/execution/iOVM_ExecutionManager.sol b/packages/contracts/contracts/optimistic-ethereum/iOVM/execution/iOVM_ExecutionManager.sol index 9be045cfc7481..3f4cfe8890047 100644 --- a/packages/contracts/contracts/optimistic-ethereum/iOVM/execution/iOVM_ExecutionManager.sol +++ b/packages/contracts/contracts/optimistic-ethereum/iOVM/execution/iOVM_ExecutionManager.sol @@ -117,7 +117,7 @@ interface iOVM_ExecutionManager { * Account Abstraction Opcodes * ******************************/ - function ovmGETNONCE() external returns (uint256 _nonce); + function ovmGETNONCE() external returns (uint64 _nonce); function ovmINCREMENTNONCE() external; function ovmCREATEEOA(bytes32 _messageHash, uint8 _v, bytes32 _r, bytes32 _s) external; diff --git a/packages/contracts/contracts/optimistic-ethereum/iOVM/execution/iOVM_StateManager.sol b/packages/contracts/contracts/optimistic-ethereum/iOVM/execution/iOVM_StateManager.sol index 1c4870a5841af..9497752ad9ba1 100644 --- a/packages/contracts/contracts/optimistic-ethereum/iOVM/execution/iOVM_StateManager.sol +++ b/packages/contracts/contracts/optimistic-ethereum/iOVM/execution/iOVM_StateManager.sol @@ -45,8 +45,8 @@ interface iOVM_StateManager { function getAccount(address _address) external view returns (Lib_OVMCodec.Account memory _account); function hasAccount(address _address) external view returns (bool _exists); function hasEmptyAccount(address _address) external view returns (bool _exists); - function setAccountNonce(address _address, uint256 _nonce) external; - function getAccountNonce(address _address) external view returns (uint256 _nonce); + function setAccountNonce(address _address, uint64 _nonce) external; + function getAccountNonce(address _address) external view returns (uint64 _nonce); function getAccountEthAddress(address _address) external view returns (address _ethAddress); function getAccountStorageRoot(address _address) external view returns (bytes32 _storageRoot); function initPendingAccount(address _address) external; diff --git a/packages/contracts/contracts/optimistic-ethereum/libraries/codec/Lib_EIP155Tx.sol b/packages/contracts/contracts/optimistic-ethereum/libraries/codec/Lib_EIP155Tx.sol index d1f64819199e4..ca3f3298893c4 100644 --- a/packages/contracts/contracts/optimistic-ethereum/libraries/codec/Lib_EIP155Tx.sol +++ b/packages/contracts/contracts/optimistic-ethereum/libraries/codec/Lib_EIP155Tx.sol @@ -20,9 +20,9 @@ library Lib_EIP155Tx { // Struct representing an EIP155 transaction. See EIP link above for more information. struct EIP155Tx { // These fields correspond to the actual RLP-encoded fields specified by EIP155. - uint256 nonce; + uint64 nonce; uint256 gasPrice; - uint256 gasLimit; + uint64 gasLimit; address to; uint256 value; bytes data; @@ -98,9 +98,9 @@ library Lib_EIP155Tx { bool isCreate = Lib_RLPReader.readBytes(decoded[3]).length == 0; return EIP155Tx({ - nonce: Lib_RLPReader.readUint256(decoded[0]), + nonce: Lib_RLPReader.readUint64(decoded[0]), gasPrice: Lib_RLPReader.readUint256(decoded[1]), - gasLimit: Lib_RLPReader.readUint256(decoded[2]), + gasLimit: Lib_RLPReader.readUint64(decoded[2]), to: Lib_RLPReader.readAddress(decoded[3]), value: Lib_RLPReader.readUint256(decoded[4]), data: Lib_RLPReader.readBytes(decoded[5]), diff --git a/packages/contracts/contracts/optimistic-ethereum/libraries/codec/Lib_OVMCodec.sol b/packages/contracts/contracts/optimistic-ethereum/libraries/codec/Lib_OVMCodec.sol index cea8f8c6d0b29..7bebe35889205 100644 --- a/packages/contracts/contracts/optimistic-ethereum/libraries/codec/Lib_OVMCodec.sol +++ b/packages/contracts/contracts/optimistic-ethereum/libraries/codec/Lib_OVMCodec.sol @@ -28,7 +28,7 @@ library Lib_OVMCodec { ***********/ struct Account { - uint256 nonce; + uint64 nonce; uint256 balance; bytes32 storageRoot; bytes32 codeHash; @@ -37,7 +37,7 @@ library Lib_OVMCodec { } struct EVMAccount { - uint256 nonce; + uint64 nonce; uint256 balance; bytes32 storageRoot; bytes32 codeHash; @@ -170,7 +170,7 @@ library Lib_OVMCodec { // index-by-index circumvents this issue. raw[0] = Lib_RLPWriter.writeBytes( Lib_Bytes32Utils.removeLeadingZeros( - bytes32(_account.nonce) + bytes32(uint256(_account.nonce)) ) ); raw[1] = Lib_RLPWriter.writeBytes( @@ -201,7 +201,7 @@ library Lib_OVMCodec { Lib_RLPReader.RLPItem[] memory accountState = Lib_RLPReader.readList(_encoded); return EVMAccount({ - nonce: Lib_RLPReader.readUint256(accountState[0]), + nonce: Lib_RLPReader.readUint64(accountState[0]), balance: Lib_RLPReader.readUint256(accountState[1]), storageRoot: Lib_RLPReader.readBytes32(accountState[2]), codeHash: Lib_RLPReader.readBytes32(accountState[3]) diff --git a/packages/contracts/contracts/optimistic-ethereum/libraries/rlp/Lib_RLPReader.sol b/packages/contracts/contracts/optimistic-ethereum/libraries/rlp/Lib_RLPReader.sol index 5e81c5de2ae62..f877b76476aef 100644 --- a/packages/contracts/contracts/optimistic-ethereum/libraries/rlp/Lib_RLPReader.sol +++ b/packages/contracts/contracts/optimistic-ethereum/libraries/rlp/Lib_RLPReader.sol @@ -328,6 +328,47 @@ library Lib_RLPReader { ); } + /** + * Reads an RLP uint64 value into a uint64. + * @param _in RLP uint64 value. + * @return Decoded uint64. + */ + function readUint64( + RLPItem memory _in + ) + internal + pure + returns ( + uint64 + ) + { + require( + _in.length <= 9, + "Invalid RLP uint64 value." + ); + + return uint64(readUint256(_in)); + } + + /** + * Reads an RLP uint64 value into a uint64. + * @param _in RLP uint64 value. + * @return Decoded uint64. + */ + function readUint64( + bytes memory _in + ) + internal + pure + returns ( + uint64 + ) + { + return readUint64( + toRLPItem(_in) + ); + } + /** * Reads an RLP bool value into a bool. * @param _in RLP bool value. diff --git a/packages/contracts/test/contracts/OVM/accounts/OVM_ECDSAContractAccount.spec.ts b/packages/contracts/test/contracts/OVM/accounts/OVM_ECDSAContractAccount.spec.ts index c28456aa4f292..d2bc886aea407 100644 --- a/packages/contracts/test/contracts/OVM/accounts/OVM_ECDSAContractAccount.spec.ts +++ b/packages/contracts/test/contracts/OVM/accounts/OVM_ECDSAContractAccount.spec.ts @@ -137,7 +137,6 @@ describe('OVM_ECDSAContractAccount', () => { // The ovmCALL is the 2nd call because the first call transfers the fee. const ovmCALL: any = Mock__OVM_ExecutionManager.smocked.ovmCALL.calls[1] - expect(ovmCALL._gasLimit).to.equal(DEFAULT_EIP155_TX.gasLimit) expect(ovmCALL._address).to.equal(DEFAULT_EIP155_TX.to) expect(ovmCALL._calldata).to.equal(DEFAULT_EIP155_TX.data) }) diff --git a/packages/contracts/test/contracts/OVM/execution/OVM_ExecutionManager/nuisance-gas.spec.ts b/packages/contracts/test/contracts/OVM/execution/OVM_ExecutionManager/nuisance-gas.spec.ts index cfa5a449f38e5..fbca4b35269f2 100644 --- a/packages/contracts/test/contracts/OVM/execution/OVM_ExecutionManager/nuisance-gas.spec.ts +++ b/packages/contracts/test/contracts/OVM/execution/OVM_ExecutionManager/nuisance-gas.spec.ts @@ -188,7 +188,7 @@ const test_nuisanceGas: TestDefinition = { // This is because there is natural gas consumption between the ovmCALL(GAS/2) and ovmCREATE, which allots nuisance gas via _getNuisanceGasLimit. // This means that the ovmCREATE exception, DOES consumes all nuisance gas allotted, but that allotment // is less than the full OVM_TX_GAS_LIMIT / 2 which is alloted to the parent ovmCALL. - nuisanceGasLeft: 0x3f9e7f, + nuisanceGasLeft: 0x3fa2e8, }, }, },