Skip to content

Commit

Permalink
Use gas and input instead of gasLimit and data (#5915)
Browse files Browse the repository at this point in the history
* decodeSignedTransaction will now return gas instead of gasLimit when parsing serialized txs

* getEthereumJsTxDataFromTransaction will use gas property if gasLimit is undefined

* Revert changes to decodeSignedTransaction in favor of refactor formatTransaction

* Update CHANGELOGs

* Remove gasLimit from MissingGasError and TransactionGasMismatchError

* Update formatTransaction to intake an optional transactionSchema so it can be used to format transactionInfo types objs

* Update formatTransaction to replace data with input

* Update plugin tests to use input instead of data

* Update sign_transaction to use input for expected sent tx obj

* Update PopulatedUnsignedBaseTransaction to use input instead of data

* Update getEthereumjsTxDataFromTransaction to get transaction.input

* Fix incorrect nonce in sign_transaction test

* Update defaultTransactionBuilder to use replace data with input

* Update test data for prepare_transaction_for_signing

* Update Contract to allow for use of input in place of data

* Fix test for cypress

* Update CHANGELOGs

* Add input to isContractInitOptions check

* CHANGELOG formatting

* Add default_transaction_builder test for input prefix

* Init ContractTransactionDataAndInputError

* Remove data and gasLimit from ContractOptions type

* Remove contractOptions.data from ternaries in contract util methods

* Add ContractTransactionDataAndInputError check in Contract constructor

* Update CHANGELOGs

---------

Co-authored-by: Junaid <86780488+jdevcs@users.noreply.github.com>
  • Loading branch information
spacesailor24 and jdevcs authored Mar 23, 2023
1 parent e172585 commit 3359773
Show file tree
Hide file tree
Showing 31 changed files with 329 additions and 173 deletions.
41 changes: 41 additions & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -1291,3 +1291,44 @@ should use 4.0.1-alpha.0 for testing.
- Fixed getPastEventsError (#5819)

## [Unreleased]

### Changed

#### web3-core

- If a transaction object with a `data` property is passed to `txInputOptionsFormatter`, it will now be replaced with `input` (#5915)

#### web3-errors

- `gasLimit` is no longer accepted as a parameter for `MissingGasError` and `TransactionGasMismatchError, and is also no longer included in error message (#5915)

#### web3-eth

- `signTransaction` will now return `gas` instead of `gasLimit` for returned transaction object regardless of what property name the provider uses (#5915)
- `formatTransaction` will now replace `data` transaction property with `input` (#5915)
- `isTransactionCall` will now check if `value.input` `isHexStrict` if provided (#5915)

#### web3-eth-contract

- `getSendTxParams` will now return `input` instead of `data` in returned transaction parameters object (#5915)
- `Contract` constructor will now thrown new `ContractTransactionDataAndInputError` if both `data` and `input` are passed in `ContractInitOptions` for `Contract` constructor (#5915)

#### web3-types

- `data` property in `TransactionOutput` was renamed to `input` (#5915)

### Added

#### web3-eth-contract

- `input` is now an acceptable property for `ContractInitOptions` in place of `data` (either can be used, but `input` is used withing the

### Removed

#### web3-eth-abi

- Removed `formatDecodedObject` function (#5934)

#### web3-eth-contract

- `data` was removed as a property of `ContractOptions` type (#5915)
4 changes: 4 additions & 0 deletions packages/web3-core/CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -84,3 +84,7 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0
- Added support of `safe` and `finalized` block tags (#5823)

## [Unreleased]

### Changed

- If a transaction object with a `data` property is passed to `txInputOptionsFormatter`, it will now be replaced with `input` (#5915)
14 changes: 7 additions & 7 deletions packages/web3-core/src/formatters.ts
Original file line number Diff line number Diff line change
Expand Up @@ -153,17 +153,17 @@ export const txInputOptionsFormatter = (options: TransactionInput): Mutable<Tran
);
}

if (!options.data && options.input) {
modifiedOptions.data = options.input;
delete modifiedOptions.input;
if (!options.input && options.data) {
modifiedOptions.input = options.data;
delete modifiedOptions.data;
}

if (options.data && !options.data.startsWith('0x')) {
modifiedOptions.data = `0x${options.data}`;
if (options.input && !options.input.startsWith('0x')) {
modifiedOptions.input = `0x${options.input}`;
}

if (modifiedOptions.data && !isHexStrict(modifiedOptions.data)) {
throw new FormatterError('The data field must be HEX encoded data.');
if (modifiedOptions.input && !isHexStrict(modifiedOptions.input)) {
throw new FormatterError('The input field must be HEX encoded data.');
}

// allow both
Expand Down
20 changes: 10 additions & 10 deletions packages/web3-core/test/unit/formatters.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -189,24 +189,24 @@ describe('formatters', () => {
);
});

it('should replace "data" with "input" if "input" is given and "data" is not', () => {
const result = txInputOptionsFormatter({ ...txInput, input: '0xff0011' });
it('should replace "input" with "data" if "data" is given and "input" is not', () => {
const result = txInputOptionsFormatter({ ...txInput, data: '0xff0011' });

expect(result).toEqual(expect.objectContaining({ data: '0xff0011' }));
expect(Object.keys(result)).not.toContain('input');
expect(result).toEqual(expect.objectContaining({ input: '0xff0011' }));
expect(Object.keys(result)).not.toContain('data');
});

it('should prefix "data" with "0x" if not already', () => {
expect(txInputOptionsFormatter({ ...txInput, data: 'ff0011' })).toEqual(
expect.objectContaining({ data: '0xff0011' }),
it('should prefix "input" with "0x" if not already', () => {
expect(txInputOptionsFormatter({ ...txInput, input: 'ff0011' })).toEqual(
expect.objectContaining({ input: '0xff0011' }),
);
});

it('should throw error if "data" is not a valid hex string', () => {
it('should throw error if "input" is not a valid hex string', () => {
jest.spyOn(utils, 'isHexStrict').mockReturnValue(false);

expect(() => txInputOptionsFormatter({ ...txInput, data: 'ff0011' })).toThrow(
'The data field must be HEX encoded data.',
expect(() => txInputOptionsFormatter({ ...txInput, input: 'ff0011' })).toThrow(
'The input field must be HEX encoded data.',
);
expect(utils.isHexStrict).toHaveBeenCalledWith('0xff0011');
});
Expand Down
4 changes: 4 additions & 0 deletions packages/web3-errors/CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -87,3 +87,7 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0
- `TransactionRevertWithCustomError` was added to handle custom solidity errors (#5854)

## [Unreleased]

### Changed

- `gasLimit` is no longer accepted as a parameter for `MissingGasError` and `TransactionGasMismatchError, and is also no longer included in error message (#5915)
1 change: 1 addition & 0 deletions packages/web3-errors/src/error_codes.ts
Original file line number Diff line number Diff line change
Expand Up @@ -41,6 +41,7 @@ export const ERR_CONTRACT_MISSING_ADDRESS = 307;
export const ERR_CONTRACT_MISSING_FROM_ADDRESS = 308;
export const ERR_CONTRACT_INSTANTIATION = 309;
export const ERR_CONTRACT_EXECUTION_REVERTED = 310;
export const ERR_CONTRACT_TX_DATA_AND_INPUT = 311;

// Transaction error codes
export const ERR_TX = 400;
Expand Down
14 changes: 13 additions & 1 deletion packages/web3-errors/src/errors/contract_errors.ts
Original file line number Diff line number Diff line change
Expand Up @@ -30,8 +30,9 @@ import {
ERR_CONTRACT_REQUIRED_CALLBACK,
ERR_CONTRACT_RESERVED_EVENT,
ERR_CONTRACT_RESOLVER_MISSING,
ERR_CONTRACT_TX_DATA_AND_INPUT,
} from '../error_codes';
import { BaseWeb3Error } from '../web3_error_base';
import { BaseWeb3Error, InvalidValueError } from '../web3_error_base';

export class Web3ContractError extends BaseWeb3Error {
public code = ERR_CONTRACT;
Expand Down Expand Up @@ -172,3 +173,14 @@ export class ContractExecutionError extends Web3ContractError {
);
}
}

export class ContractTransactionDataAndInputError extends InvalidValueError {
public code = ERR_CONTRACT_TX_DATA_AND_INPUT;

public constructor(value: { data: HexString | undefined; input: HexString | undefined }) {
super(
`data: ${value.data ?? 'undefined'}, input: ${value.input ?? 'undefined'}`,
'You can\'t have "data" and "input" as properties of a contract at the same time, please use either "data" or "input" instead.',
);
}
}
22 changes: 10 additions & 12 deletions packages/web3-errors/src/errors/transaction_errors.ts
Original file line number Diff line number Diff line change
Expand Up @@ -310,17 +310,16 @@ export class MissingGasError extends InvalidValueError {

public constructor(value: {
gas: Numbers | undefined;
gasLimit: Numbers | undefined;
gasPrice: Numbers | undefined;
maxPriorityFeePerGas: Numbers | undefined;
maxFeePerGas: Numbers | undefined;
}) {
super(
`gas: ${value.gas ?? 'undefined'}, gasLimit: ${
value.gasLimit ?? 'undefined'
}, gasPrice: ${value.gasPrice ?? 'undefined'}, maxPriorityFeePerGas: ${
value.maxPriorityFeePerGas ?? 'undefined'
}, maxFeePerGas: ${value.maxFeePerGas ?? 'undefined'}`,
`gas: ${value.gas ?? 'undefined'}, gasPrice: ${
value.gasPrice ?? 'undefined'
}, maxPriorityFeePerGas: ${value.maxPriorityFeePerGas ?? 'undefined'}, maxFeePerGas: ${
value.maxFeePerGas ?? 'undefined'
}`,
'"gas" is missing',
);
}
Expand All @@ -331,17 +330,16 @@ export class TransactionGasMismatchError extends InvalidValueError {

public constructor(value: {
gas: Numbers | undefined;
gasLimit: Numbers | undefined;
gasPrice: Numbers | undefined;
maxPriorityFeePerGas: Numbers | undefined;
maxFeePerGas: Numbers | undefined;
}) {
super(
`gas: ${value.gas ?? 'undefined'}, gasLimit: ${
value.gasLimit ?? 'undefined'
}, gasPrice: ${value.gasPrice ?? 'undefined'}, maxPriorityFeePerGas: ${
value.maxPriorityFeePerGas ?? 'undefined'
}, maxFeePerGas: ${value.maxFeePerGas ?? 'undefined'}`,
`gas: ${value.gas ?? 'undefined'}, gasPrice: ${
value.gasPrice ?? 'undefined'
}, maxPriorityFeePerGas: ${value.maxPriorityFeePerGas ?? 'undefined'}, maxFeePerGas: ${
value.maxFeePerGas ?? 'undefined'
}`,
'transaction must specify legacy or fee market gas properties, not both',
);
}
Expand Down
14 changes: 14 additions & 0 deletions packages/web3-eth-contract/CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -236,3 +236,17 @@ const transactionHash = receipt.transactionHash;
- `decodeErrorData` is no longer exported (method was moved to `web3-eth-abi` and renamed `decodeContractErrorData`) (#5844)

## [Unreleased]

### Added

- `input` is now an acceptable property for `ContractInitOptions` in place of `data` (either can be used, but `input` is used withing the
`Contract` class) (#5915)

### Changed

- `getSendTxParams` will now return `input` instead of `data` in returned transaction parameters object (#5915)
- `Contract` constructor will now thrown new `ContractTransactionDataAndInputError` if both `data` and `input` are passed in `ContractInitOptions` for `Contract` constructor (#5915)

### Removed

- `data` was removed as a property of `ContractOptions` type (#5915)
55 changes: 32 additions & 23 deletions packages/web3-eth-contract/src/contract.ts
Original file line number Diff line number Diff line change
Expand Up @@ -16,7 +16,12 @@ along with web3.js. If not, see <http://www.gnu.org/licenses/>.
*/

import { Web3Context, Web3EventEmitter, Web3PromiEvent, Web3ConfigEvent } from 'web3-core';
import { ContractExecutionError, SubscriptionError, Web3ContractError } from 'web3-errors';
import {
ContractExecutionError,
ContractTransactionDataAndInputError,
SubscriptionError,
Web3ContractError,
} from 'web3-errors';
import {
createAccessList,
call,
Expand Down Expand Up @@ -293,6 +298,19 @@ export class Contract<Abi extends ContractAbi>
contextOrReturnFormat?: Web3ContractContext | Web3Context | DataFormat,
returnFormat?: DataFormat,
) {
// eslint-disable-next-line no-nested-ternary
const options = isContractInitOptions(addressOrOptionsOrContext)
? addressOrOptionsOrContext
: isContractInitOptions(optionsOrContextOrReturnFormat)
? optionsOrContextOrReturnFormat
: undefined;

if (!isNullish(options) && !isNullish(options.data) && !isNullish(options.input))
throw new ContractTransactionDataAndInputError({
data: options.data as HexString,
input: options.input as HexString,
});

let contractContext;
if (isWeb3ContractContext(addressOrOptionsOrContext)) {
contractContext = addressOrOptionsOrContext;
Expand Down Expand Up @@ -340,13 +358,6 @@ export class Contract<Abi extends ContractAbi>
const address =
typeof addressOrOptionsOrContext === 'string' ? addressOrOptionsOrContext : undefined;

// eslint-disable-next-line no-nested-ternary
const options = isContractInitOptions(addressOrOptionsOrContext)
? addressOrOptionsOrContext
: isContractInitOptions(optionsOrContextOrReturnFormat)
? optionsOrContextOrReturnFormat
: undefined;

this._parseAndSetJsonInterface(jsonInterface, returnDataFormat);

if (!isNullish(address)) {
Expand All @@ -358,9 +369,8 @@ export class Contract<Abi extends ContractAbi>
jsonInterface: this._jsonInterface,
gas: options?.gas ?? options?.gasLimit,
gasPrice: options?.gasPrice,
gasLimit: options?.gasLimit,
from: options?.from,
data: options?.data,
input: options?.input ?? options?.data,
};

this.syncWithContext = (options as ContractInitOptions)?.syncWithContext ?? false;
Expand Down Expand Up @@ -465,9 +475,8 @@ export class Contract<Abi extends ContractAbi>
{
gas: this.options.gas,
gasPrice: this.options.gasPrice,
gasLimit: this.options.gasLimit,
from: this.options.from,
data: this.options.data,
input: this.options.input,
provider: this.currentProvider,
syncWithContext: this.syncWithContext,
},
Expand All @@ -479,9 +488,8 @@ export class Contract<Abi extends ContractAbi>
{
gas: this.options.gas,
gasPrice: this.options.gasPrice,
gasLimit: this.options.gasLimit,
from: this.options.from,
data: this.options.data,
input: this.options.input,
provider: this.currentProvider,
syncWithContext: this.syncWithContext,
},
Expand All @@ -498,7 +506,7 @@ export class Contract<Abi extends ContractAbi>
*
* ```ts
* myContract.deploy({
* data: '0x12345...',
* input: '0x12345...',
* arguments: [123, 'My String']
* })
* .send({
Expand Down Expand Up @@ -535,7 +543,7 @@ export class Contract<Abi extends ContractAbi>
*
* // Simply encoding
* myContract.deploy({
* data: '0x12345...',
* input: '0x12345...',
* arguments: [123, 'My String']
* })
* .encodeABI();
Expand All @@ -544,7 +552,7 @@ export class Contract<Abi extends ContractAbi>
*
* // Gas estimation
* myContract.deploy({
* data: '0x12345...',
* input: '0x12345...',
* arguments: [123, 'My String']
* })
* .estimateGas(function(err, gas){
Expand All @@ -559,6 +567,7 @@ export class Contract<Abi extends ContractAbi>
* The byte code of the contract.
*/
data?: HexString;
input?: HexString;
/**
* The arguments which get passed to the constructor on deployment.
*/
Expand All @@ -574,19 +583,19 @@ export class Contract<Abi extends ContractAbi>
} as AbiConstructorFragment;
}

const data = format(
const _input = format(
{ eth: 'bytes' },
deployOptions?.data ?? this.options.data,
deployOptions?.input ?? deployOptions?.data ?? this.options.input,
DEFAULT_RETURN_FORMAT,
);

if (!data || data.trim() === '0x') {
if (!_input || _input.trim() === '0x') {
throw new Web3ContractError('contract creation without any data provided.');
}

const args = deployOptions?.arguments ?? [];

const contractOptions = { ...this.options, data };
const contractOptions: ContractOptions = { ...this.options, input: _input };

return {
arguments: args,
Expand Down Expand Up @@ -631,7 +640,7 @@ export class Contract<Abi extends ContractAbi>
encodeMethodABI(
abi as AbiFunctionFragment,
args as unknown[],
format({ eth: 'bytes' }, data as Bytes, DEFAULT_RETURN_FORMAT),
format({ eth: 'bytes' }, _input as Bytes, DEFAULT_RETURN_FORMAT),
),
};
}
Expand Down Expand Up @@ -1040,7 +1049,7 @@ export class Contract<Abi extends ContractAbi>
let modifiedContractOptions = contractOptions ?? this.options;
modifiedContractOptions = {
...modifiedContractOptions,
data: undefined,
input: undefined,
from: modifiedContractOptions.from ?? this.defaultAccount ?? undefined,
};

Expand Down
Loading

0 comments on commit 3359773

Please sign in to comment.