Repository: ecadlabs/taquito
Pull request #1871 (2022-08-31 22:25:22)

1743 support emit instruc
Adds the `EMIT` instruction to the retStack function

adds two passing test and one invalid contract test 

current unknowns if done correctly are:

how is the type persisted to be added with the Event

when the `CONS` instruction is added to the stack it puts the `operation` into a list but loses the annotation.

is there a place missed to add the instruction `ty` as well as the annotated `tag` ? 

Before submitting this PR, please make sure:

- [ ] Your code builds cleanly without any errors or warnings
- [ ] You have added unit tests
- [ ] You have added integration tests (if relevant/appropriate)
- [ ] All public methods or types have TypeDoc coverage with a complete description, and ideally an @example
- [ ] You have added or updated corresponding documentation
- [ ] If relevant, you have written a first draft summary describing the change for inclusion in Release Notes. 

## Release Note Draft Snippet

__If relevant, please write a summary of your change that will be suitable for
inclusion in the Release Notes for the next Taquito release.__


github-actions[bot]: New packages have been deployed to the preview repository at https://npm.preview.tezostaquito.io/.

### Published packages:
```
npm i @taquito/local-forging@13.0.1-1d02cd10--1871 --registry https://npm.preview.tezostaquito.io/
npm i @taquito/rpc@13.0.1-1d02cd10--1871 --registry https://npm.preview.tezostaquito.io/
npm i @taquito/signer@13.0.1-1d02cd10--1871 --registry https://npm.preview.tezostaquito.io/
npm i @taquito/taquito@13.0.1-1d02cd10--1871 --registry https://npm.preview.tezostaquito.io/
npm i @taquito/remote-signer@13.0.1-1d02cd10--1871 --registry https://npm.preview.tezostaquito.io/
npm i @taquito/tezbridge-wallet@13.0.1-1d02cd10--1871 --registry https://npm.preview.tezostaquito.io/
npm i @taquito/michelson-encoder@13.0.1-1d02cd10--1871 --registry https://npm.preview.tezostaquito.io/
npm i @taquito/contracts-library@13.0.1-1d02cd10--1871 --registry https://npm.preview.tezostaquito.io/
npm i @taquito/ledger-signer@13.0.1-1d02cd10--1871 --registry https://npm.preview.tezostaquito.io/
npm i @taquito/beacon-wallet@13.0.1-1d02cd10--1871 --registry https://npm.preview.tezostaquito.io/
npm i @taquito/http-utils@13.0.1-1d02cd10--1871 --registry https://npm.preview.tezostaquito.io/
npm i @taquito/tezbridge-signer@13.0.1-1d02cd10--1871 --registry https://npm.preview.tezostaquito.io/
npm i @taquito/michel-codec@13.0.1-1d02cd10--1871 --registry https://npm.preview.tezostaquito.io/
npm i @taquito/utils@13.0.1-1d02cd10--1871 --registry https://npm.preview.tezostaquito.io/
npm i @taquito/tzip12@13.0.1-1d02cd10--1871 --registry https://npm.preview.tezostaquito.io/
npm i @taquito/tzip16@13.0.1-1d02cd10--1871 --registry https://npm.preview.tezostaquito.io/
```
<!-- Sticky Pull Request Commentdeploy-packages -->
codecov-commenter: # [Codecov](https://codecov.io/gh/ecadlabs/taquito/pull/1871?src=pr&el=h1&utm_medium=referral&utm_source=github&utm_content=comment&utm_campaign=pr+comments&utm_term=ecadlabs) Report
> Merging [#1871](https://codecov.io/gh/ecadlabs/taquito/pull/1871?src=pr&el=desc&utm_medium=referral&utm_source=github&utm_content=comment&utm_campaign=pr+comments&utm_term=ecadlabs) (6977e8b) into [kathmandu](https://codecov.io/gh/ecadlabs/taquito/commit/14c8b28f1f2f298758b5bdc9adb7134f2c979883?el=desc&utm_medium=referral&utm_source=github&utm_content=comment&utm_campaign=pr+comments&utm_term=ecadlabs) (14c8b28) will **decrease** coverage by `0.06%`.
> The diff coverage is `87.50%`.

```diff
@@              Coverage Diff              @@
##           kathmandu    #1871      +/-   ##
=============================================
- Coverage      80.94%   80.87%   -0.07%     
=============================================
  Files            205      205              
  Lines          11473    11484      +11     
  Branches        2834     2839       +5     
=============================================
+ Hits            9287     9288       +1     
- Misses          2080     2089       +9     
- Partials         106      107       +1     
```


| [Impacted Files](https://codecov.io/gh/ecadlabs/taquito/pull/1871?src=pr&el=tree&utm_medium=referral&utm_source=github&utm_content=comment&utm_campaign=pr+comments&utm_term=ecadlabs) | Coverage Δ | |
|---|---|---|
| [...ges/taquito-michel-codec/src/michelson-contract.ts](https://codecov.io/gh/ecadlabs/taquito/pull/1871/diff?src=pr&el=tree&utm_medium=referral&utm_source=github&utm_content=comment&utm_campaign=pr+comments&utm_term=ecadlabs#diff-cGFja2FnZXMvdGFxdWl0by1taWNoZWwtY29kZWMvc3JjL21pY2hlbHNvbi1jb250cmFjdC50cw==) | `26.78% <0.00%> (-0.49%)` | :arrow_down: |
| [...ckages/taquito-michel-codec/src/michelson-types.ts](https://codecov.io/gh/ecadlabs/taquito/pull/1871/diff?src=pr&el=tree&utm_medium=referral&utm_source=github&utm_content=comment&utm_campaign=pr+comments&utm_term=ecadlabs#diff-cGFja2FnZXMvdGFxdWl0by1taWNoZWwtY29kZWMvc3JjL21pY2hlbHNvbi10eXBlcy50cw==) | `96.77% <ø> (ø)` | |
| [...es/taquito-michel-codec/src/michelson-typecheck.ts](https://codecov.io/gh/ecadlabs/taquito/pull/1871/diff?src=pr&el=tree&utm_medium=referral&utm_source=github&utm_content=comment&utm_campaign=pr+comments&utm_term=ecadlabs#diff-cGFja2FnZXMvdGFxdWl0by1taWNoZWwtY29kZWMvc3JjL21pY2hlbHNvbi10eXBlY2hlY2sudHM=) | `81.27% <100.00%> (+0.11%)` | :arrow_up: |
| [...es/taquito-michel-codec/src/michelson-validator.ts](https://codecov.io/gh/ecadlabs/taquito/pull/1871/diff?src=pr&el=tree&utm_medium=referral&utm_source=github&utm_content=comment&utm_campaign=pr+comments&utm_term=ecadlabs#diff-cGFja2FnZXMvdGFxdWl0by1taWNoZWwtY29kZWMvc3JjL21pY2hlbHNvbi12YWxpZGF0b3IudHM=) | `89.95% <100.00%> (+0.14%)` | :arrow_up: |
| [packages/taquito/src/contract/contract.ts](https://codecov.io/gh/ecadlabs/taquito/pull/1871/diff?src=pr&el=tree&utm_medium=referral&utm_source=github&utm_content=comment&utm_campaign=pr+comments&utm_term=ecadlabs#diff-cGFja2FnZXMvdGFxdWl0by9zcmMvY29udHJhY3QvY29udHJhY3QudHM=) | `91.66% <0.00%> (-2.09%)` | :arrow_down: |
| [packages/taquito-michel-codec/src/binary.ts](https://codecov.io/gh/ecadlabs/taquito/pull/1871/diff?src=pr&el=tree&utm_medium=referral&utm_source=github&utm_content=comment&utm_campaign=pr+comments&utm_term=ecadlabs#diff-cGFja2FnZXMvdGFxdWl0by1taWNoZWwtY29kZWMvc3JjL2JpbmFyeS50cw==) | `76.82% <0.00%> (-0.86%)` | :arrow_down: |
| [...ages/taquito/src/contract/rpc-contract-provider.ts](https://codecov.io/gh/ecadlabs/taquito/pull/1871/diff?src=pr&el=tree&utm_medium=referral&utm_source=github&utm_content=comment&utm_campaign=pr+comments&utm_term=ecadlabs#diff-cGFja2FnZXMvdGFxdWl0by9zcmMvY29udHJhY3QvcnBjLWNvbnRyYWN0LXByb3ZpZGVyLnRz) | `93.86% <0.00%> (-0.48%)` | :arrow_down: |
| [...es/taquito-michelson-encoder/src/schema/storage.ts](https://codecov.io/gh/ecadlabs/taquito/pull/1871/diff?src=pr&el=tree&utm_medium=referral&utm_source=github&utm_content=comment&utm_campaign=pr+comments&utm_term=ecadlabs#diff-cGFja2FnZXMvdGFxdWl0by1taWNoZWxzb24tZW5jb2Rlci9zcmMvc2NoZW1hL3N0b3JhZ2UudHM=) | `80.15% <0.00%> (-0.47%)` | :arrow_down: |

Help us with your feedback. Take ten seconds to tell us [how you rate us](https://about.codecov.io/nps?utm_medium=referral&utm_source=github&utm_content=comment&utm_campaign=pr+comments&utm_term=ecadlabs). Have a feature suggestion? [Share it here.](https://app.codecov.io/gh/feedback/?utm_medium=referral&utm_source=github&utm_content=comment&utm_campaign=pr+comments&utm_term=ecadlabs)


Patch:
diff --git a/docs/increase_paid_storage.md b/docs/increase_paid_storage.md
new file mode 100644
index 000000000..c6ce4a995
--- /dev/null
+++ b/docs/increase_paid_storage.md
@@ -0,0 +1,72 @@
+---
+title: Increase Paid Storage
+author: Davis Sawali
+---
+
+Increase Paid Storage is a new operation available for use starting from Protocol 14 (Kathmandu). It is a new operation that enables a payer to increase the paid storage of a smart contract by a certain byte amount.
+
+This helps resolve an issue where several operations on the same contract would fail when they are added at the same level due to the storage limit being lower than the `paid_storage_size_diff`.
+
+For more information on this change, refer to this [MR](https://gitlab.com/tezos/tezos/-/merge_requests/5605) in the Tezos codebase.
+## Examples
+Similar to other operations, the Increase Paid Storage operation will be available in the Contract API (and later, the wallet API).
+
+### Simple Usage
+```js
+const op = await Tezos.contract.increasePaidStorage({
+  amount: 2,
+  destination: 'SMART_CONTRACT_ADDRESS'
+});
+
+await op.confirmation();
+```
+- `amount` is the the number of `bytes` you want to increase the paid storage by
+- `destination` is the `KT1` address of the smart contract which storage you would like to increase
+
+After waiting for the operation confirmation, you will also have access to various getters of the operation such as `status`, `amount`, `destination`, `fee`, `gasLimit`, `errors`, `storageLimit`, `consumedMilligas`.
+
+### Usage in Batches
+```js
+const op = await Tezos.contract
+    .batch()
+    .withOrigination({
+      balance: "1",
+      code: `parameter string;
+      storage string;
+      code {CAR;
+            PUSH string "Hello ";
+            CONCAT;
+            NIL operation; PAIR};
+      `,
+      init: `"test"`
+    })
+    .withIncreasePaidStorage({
+      amount: 1,
+      destination: 'SMART_CONTRACT_ADDRESS'
+    })
+    .send();
+    
+    await op.confirmation();
+```
+
+or 
+```js
+const op = await Tezos.contract.batch([
+    {
+      kind: 'origination', 
+      balance: '1', 
+      code: SAMPLE_CODE, 
+      storage: 0 
+    },
+    { 
+      kind: 'increase_paid_storage',
+      amount: 1, 
+      destination: 'SMART_CONTRACT_ADDRESS' 
+    } 
+    ])
+    .send();
+
+await op.confirmation();
+```
+
+Both syntax will work fine for batching any operations, including `increase_paid_storage`.
\ No newline at end of file
diff --git a/packages/taquito-michel-codec/src/binary.ts b/packages/taquito-michel-codec/src/binary.ts
index db177d76c..4a8864090 100644
--- a/packages/taquito-michel-codec/src/binary.ts
+++ b/packages/taquito-michel-codec/src/binary.ts
@@ -185,6 +185,7 @@ const primitives: PrimID[] = [
   'view',
   'constant',
   'SUB_MUTEZ',
+  'EMIT',
 ];
 
 const primTags: { [key in PrimID]?: number } & { [key: string]: number | undefined } =
diff --git a/packages/taquito-michel-codec/src/michelson-contract.ts b/packages/taquito-michel-codec/src/michelson-contract.ts
index e8b064375..c3ea6e452 100644
--- a/packages/taquito-michel-codec/src/michelson-contract.ts
+++ b/packages/taquito-michel-codec/src/michelson-contract.ts
@@ -62,7 +62,9 @@ export class Contract {
     if (expr === null) {
       throw new InvalidTypeExpressionError('empty type expression');
     }
-    if (assertMichelsonType(expr) && assertTypeAnnotationsValid(expr)) {
+    // remove assertTypeAnnotationsValid from if block because: () => void || throw error
+    if (assertMichelsonType(expr)) {
+      assertTypeAnnotationsValid(expr)
       return expr;
     }
     throw undefined;
diff --git a/packages/taquito-michel-codec/src/michelson-typecheck.ts b/packages/taquito-michel-codec/src/michelson-typecheck.ts
index f32b3e93b..d6cdfc76d 100644
--- a/packages/taquito-michel-codec/src/michelson-typecheck.ts
+++ b/packages/taquito-michel-codec/src/michelson-typecheck.ts
@@ -661,7 +661,7 @@ function functionTypeInternal(
   function rethrow<T extends unknown[], U>(fn: (...args: T) => U) {
     return (...args: T): U => {
       try {
-        return fn(...args);
+         return fn(...args);
       } catch (err) {
         if (err instanceof MichelsonError) {
           throw new MichelsonInstructionError(instruction, stack, err.message);
@@ -2004,9 +2004,20 @@ function functionTypeInternal(
         ensurePushableType(s[0]);
         return [annotateVar({ prim: 'option', args: [instruction.args[1]] }), ...stack.slice(2)];
       }
+
       case 'MIN_BLOCK_TIME':
         return [annotateVar({ prim: 'nat' }), ...stack];
 
+      case 'EMIT': {
+        const ia = instructionAnn({ f: 1, t: 1});
+        if (instruction.args) {
+          const s = args(0, null);
+          ensureTypesEqual(s[0], instruction.args[0]);
+          return [annotate({ prim: 'operation' }, ia), ...stack.slice(1)];
+        }
+          return [annotate({ prim: 'operation'}, ia), ...stack.slice(1)];
+      }
+
       default:
         throw new MichelsonError(
           instruction as MichelsonCode,
diff --git a/packages/taquito-michel-codec/src/michelson-types.ts b/packages/taquito-michel-codec/src/michelson-types.ts
index 84be85122..c4d537f21 100644
--- a/packages/taquito-michel-codec/src/michelson-types.ts
+++ b/packages/taquito-michel-codec/src/michelson-types.ts
@@ -113,6 +113,7 @@ type MichelsonRegularInstructionID =
   | 'UPDATE'
   | 'CAST'
   | 'VIEW'
+  | 'EMIT'
   // legacy
   | 'CREATE_ACCOUNT'
   | 'STEPS_TO_QUOTA';
@@ -142,6 +143,7 @@ export type MichelsonInstruction =
   | InstrX<'LAMBDA', [MichelsonType, MichelsonType, InstructionList]>
   | InstrX<'DIP', [IntLiteral, InstructionList] | [InstructionList]>
   | InstrX<'VIEW', [StringLiteral, MichelsonType]>
+  | InstrX<'EMIT', [MichelsonType]>
   | InstrPrim<'DROP' | 'PAIR' | 'UNPAIR' | 'DUP' | 'GET' | 'UPDATE', [IntLiteral]>;
 
 // Types
diff --git a/packages/taquito-michel-codec/src/michelson-validator.ts b/packages/taquito-michel-codec/src/michelson-validator.ts
index 3e97e7dc0..4d44a2b90 100644
--- a/packages/taquito-michel-codec/src/michelson-validator.ts
+++ b/packages/taquito-michel-codec/src/michelson-validator.ts
@@ -99,6 +99,7 @@ export const instructionIDs: Record<MichelsonInstruction['prim'], true> = Object
     DROP: true,
     DUG: true,
     DUP: true,
+    EMIT: true,
     EMPTY_BIG_MAP: true,
     EMPTY_MAP: true,
     EMPTY_SET: true,
@@ -419,6 +420,15 @@ export function assertMichelsonInstruction(ex: Expr): ex is MichelsonCode {
         }
         break;
 
+      case 'EMIT':
+        if (ex.args && ex.args.length > 0) {
+          assertArgs(ex, 1);
+        } else {
+          assertArgs(ex, 0)
+        }
+        break;
+
+
       default:
         throw new MichelsonValidationError(ex, 'instruction expected');
     }
diff --git a/packages/taquito-rpc/src/opkind.ts b/packages/taquito-rpc/src/opkind.ts
index 0c3883d35..9fb1316e2 100644
--- a/packages/taquito-rpc/src/opkind.ts
+++ b/packages/taquito-rpc/src/opkind.ts
@@ -26,4 +26,6 @@ export enum OpKind {
   TX_ROLLUP_DISPATCH_TICKETS = 'tx_rollup_dispatch_tickets',
   TRANSFER_TICKET = 'transfer_ticket',
   INCREASE_PAID_STORAGE = 'increase_paid_storage',
+  VDF_REVELATION = 'vdf_revelation',
+  EVENT = 'event',
 }
diff --git a/packages/taquito-rpc/src/types.ts b/packages/taquito-rpc/src/types.ts
index eec9cbb9c..176e2c090 100644
--- a/packages/taquito-rpc/src/types.ts
+++ b/packages/taquito-rpc/src/types.ts
@@ -106,6 +106,9 @@ export interface DelegatesResponse {
   deactivated: boolean;
   grace_period: number;
   voting_power?: BigNumber;
+  current_ballot?: OperationContentsBallotEnum;
+  current_proposals?: string[];
+  remaining_proposals?: number;
 }
 
 interface Frozenbalancebycycle {
@@ -223,6 +226,11 @@ export interface OperationContentsRevelation {
   nonce: string;
 }
 
+export interface OperationContentsVdfRevelation {
+  kind: OpKind.VDF_REVELATION;
+  solution: string[];
+}
+
 export interface OperationContentsDoubleEndorsement {
   kind: OpKind.DOUBLE_ENDORSEMENT_EVIDENCE;
   op1: InlinedEndorsement;
@@ -439,6 +447,7 @@ export type OperationContents =
   | OperationContentsPreEndorsement
   | OperationContentsDoublePreEndorsement
   | OperationContentsRevelation
+  | OperationContentsVdfRevelation
   | OperationContentsDoubleEndorsement
   | OperationContentsDoubleBaking
   | OperationContentsActivateAccount
@@ -834,6 +843,12 @@ export interface OperationContentsAndResultIncreasePaidStorage {
   metadata: OperationContentsAndResultMetadataIncreasePaidStorage;
 }
 
+export interface OperationContentsAndResultVdfRevelation {
+  kind: OpKind.VDF_REVELATION;
+  solution: string[];
+  metadata: OperationContentsAndResultMetadata;
+}
+
 export type OperationContentsAndResult =
   | OperationContentsAndResultEndorsement
   | OperationContentsAndResultPreEndorsement
@@ -860,7 +875,8 @@ export type OperationContentsAndResult =
   | OperationContentsAndResultTxRollupRemoveCommitment
   | OperationContentsAndResultTxRollupRejection
   | OperationContentsAndResultTransferTicket
-  | OperationContentsAndResultIncreasePaidStorage;
+  | OperationContentsAndResultIncreasePaidStorage
+  | OperationContentsAndResultVdfRevelation;
 
 export enum OPERATION_METADATA {
   TOO_LARGE = 'too large',
@@ -1058,9 +1074,15 @@ export interface ScriptedContracts {
   storage: MichelsonV1Expression;
 }
 
-export interface BondId {
-  tx_rollup: string;
-}
+export type BondId =
+  | {
+      sc_rollup?: never;
+      tx_rollup: string;
+    }
+  | {
+      sc_rollup: string;
+      tx_rollup?: never;
+    };
 
 export interface OperationBalanceUpdatesItem {
   kind: BalanceUpdateKindEnum;
@@ -1089,7 +1111,8 @@ export type InternalOperationResultKindEnum =
   | OpKind.REVEAL
   | OpKind.TRANSACTION
   | OpKind.ORIGINATION
-  | OpKind.DELEGATION;
+  | OpKind.DELEGATION
+  | OpKind.EVENT;
 
 export type SuccessfulManagerOperationResultKindEnum =
   | OpKind.REVEAL
@@ -1101,7 +1124,8 @@ export type InternalOperationResultEnum =
   | OperationResultReveal
   | OperationResultTransaction
   | OperationResultDelegation
-  | OperationResultOrigination;
+  | OperationResultOrigination
+  | OperationResultEvent;
 
 export interface OperationResultTxRollupOrigination {
   status: OperationResultStatusEnum;
@@ -1273,6 +1297,9 @@ export interface InternalOperationResult {
   value?: MichelsonV1Expression;
   limit?: string;
   result: InternalOperationResultEnum;
+  type?: MichelsonV1Expression;
+  tag?: string;
+  payload?: MichelsonV1Expression;
 }
 
 export interface SuccessfulManagerOperationResult {
@@ -1412,6 +1439,12 @@ export interface OperationResultOrigination {
   lazy_storage_diff?: LazyStorageDiff[];
 }
 
+export interface OperationResultEvent {
+  status: OperationResultStatusEnum;
+  consumed_milligas?: string;
+  errors?: TezosGenericOperationError[];
+}
+
 export interface OperationContentsAndResultMetadataOrigination {
   balance_updates: OperationMetadataBalanceUpdates[];
   operation_result: OperationResultOrigination;
diff --git a/packages/taquito/src/batch/rpc-batch-provider.ts b/packages/taquito/src/batch/rpc-batch-provider.ts
index a168ab651..eca848eb2 100644
--- a/packages/taquito/src/batch/rpc-batch-provider.ts
+++ b/packages/taquito/src/batch/rpc-batch-provider.ts
@@ -11,6 +11,7 @@ import {
   createTransferOperation,
   createTxRollupBatchOperation,
   createTransferTicketOperation,
+  createIncreasePaidStorageOperation,
 } from '../contract/prepare';
 import { BatchOperation } from '../operations/batch-operation';
 import { OperationEmitter } from '../operations/operation-emitter';
@@ -28,6 +29,7 @@ import {
   TxRollupOriginateParams,
   TxRollupBatchParams,
   TransferTicketParams,
+  IncreasePaidStorageParams,
 } from '../operations/types';
 import { OpKind } from '@taquito/rpc';
 import { ContractMethodObject } from '../contract/contract-methods/contract-method-object-param';
@@ -87,7 +89,7 @@ export class OperationBatch extends OperationEmitter {
       throw new InvalidContractAddressError(params.destination);
     }
     this.operations.push({ kind: OpKind.TRANSFER_TICKET, ...params });
-    return this
+    return this;
   }
 
   /**
@@ -157,6 +159,17 @@ export class OperationBatch extends OperationEmitter {
     return this;
   }
 
+  /**
+   *
+   * @description Add an operation to increase paid storage to the batch
+   *
+   * @param params IncreasePaidStorage operation parameter
+   */
+  withIncreasePaidStorage(params: IncreasePaidStorageParams) {
+    this.operations.push({ kind: OpKind.INCREASE_PAID_STORAGE, ...params });
+    return this;
+  }
+
   /**
    *
    * @description Add an operation to originate a rollup to the batch
@@ -203,6 +216,10 @@ export class OperationBatch extends OperationEmitter {
         return createRegisterGlobalConstantOperation({
           ...param,
         });
+      case OpKind.INCREASE_PAID_STORAGE:
+        return createIncreasePaidStorageOperation({
+          ...param,
+        });
       case OpKind.TX_ROLLUP_ORIGINATION:
         return createTxRollupOriginationOperation({
           ...param,
@@ -213,8 +230,8 @@ export class OperationBatch extends OperationEmitter {
         });
       case OpKind.TRANSFER_TICKET:
         return createTransferTicketOperation({
-          ...param
-        })
+          ...param,
+        });
       default:
         throw new InvalidOperationKindError((param as any).kind);
     }
@@ -244,6 +261,9 @@ export class OperationBatch extends OperationEmitter {
         case OpKind.REGISTER_GLOBAL_CONSTANT:
           this.withRegisterGlobalConstant(param);
           break;
+        case OpKind.INCREASE_PAID_STORAGE:
+          this.withIncreasePaidStorage(param);
+          break;
         case OpKind.TX_ROLLUP_ORIGINATION:
           this.withTxRollupOrigination(param);
           break;
diff --git a/packages/taquito/src/contract/interface.ts b/packages/taquito/src/contract/interface.ts
index f15150c16..799456ef4 100644
--- a/packages/taquito/src/contract/interface.ts
+++ b/packages/taquito/src/contract/interface.ts
@@ -18,9 +18,11 @@ import {
   RegisterGlobalConstantParams,
   TxRollupOriginateParams,
   TxRollupBatchParams,
+  IncreasePaidStorageParams,
 } from '../operations/types';
 import { ContractAbstraction, ContractStorageType, DefaultContractType } from './contract';
 import { TxRollupBatchOperation } from '../operations/tx-rollup-batch-operation';
+import { IncreasePaidStorageOperation } from '../operations/increase-paid-storage-operation';
 
 export type ContractSchema = Schema | unknown;
 
@@ -180,6 +182,16 @@ export interface ContractProvider extends StorageProvider {
     params: RegisterGlobalConstantParams
   ): Promise<RegisterGlobalConstantOperation>;
 
+  /**
+   *
+   * @description Increase the amount of bytes in a smart contract storage by paying a fee
+   *
+   * @returns An operation handle with the result from the rpc node
+   *
+   * @param params IncreasePaidStorage operation parameter
+   */
+  increasePaidStorage(params: IncreasePaidStorageParams): Promise<IncreasePaidStorageOperation>;
+
   /**
    *
    * @description Originate a new tx rollup. Will sign and inject an operation using the current context
diff --git a/packages/taquito/src/contract/prepare.ts b/packages/taquito/src/contract/prepare.ts
index 87fd74ac7..17366de72 100644
--- a/packages/taquito/src/contract/prepare.ts
+++ b/packages/taquito/src/contract/prepare.ts
@@ -19,6 +19,8 @@ import {
   RPCTxRollupBatchOperation,
   TransferTicketParams,
   RPCTransferTicketOperation,
+  IncreasePaidStorageParams,
+  RPCIncreasePaidStorageOperation,
 } from '../operations/types';
 import { DEFAULT_FEE, DEFAULT_GAS_LIMIT, DEFAULT_STORAGE_LIMIT } from '../constants';
 import { format } from '../format';
@@ -218,7 +220,7 @@ export const createTransferTicketOperation = async ({
   source,
   fee,
   gasLimit,
-  storageLimit
+  storageLimit,
 }: TransferTicketParams) => {
   return {
     kind: OpKind.TRANSFER_TICKET,
@@ -231,6 +233,25 @@ export const createTransferTicketOperation = async ({
     ticket_ticketer: ticketTicketer,
     ticket_amount: ticketAmount,
     destination,
-    entrypoint
-  } as RPCTransferTicketOperation
-}
+    entrypoint,
+  } as RPCTransferTicketOperation;
+};
+
+export const createIncreasePaidStorageOperation = async ({
+  source,
+  fee,
+  gasLimit,
+  storageLimit,
+  amount,
+  destination,
+}: IncreasePaidStorageParams) => {
+  return {
+    kind: OpKind.INCREASE_PAID_STORAGE,
+    source,
+    fee,
+    gas_limit: gasLimit,
+    storage_limit: storageLimit,
+    amount,
+    destination,
+  } as RPCIncreasePaidStorageOperation;
+};
diff --git a/packages/taquito/src/contract/rpc-contract-provider.ts b/packages/taquito/src/contract/rpc-contract-provider.ts
index 6f1ca7558..835b35247 100644
--- a/packages/taquito/src/contract/rpc-contract-provider.ts
+++ b/packages/taquito/src/contract/rpc-contract-provider.ts
@@ -24,6 +24,7 @@ import {
   withKind,
   TxRollupBatchParams,
   TransferTicketParams,
+  IncreasePaidStorageParams,
 } from '../operations/types';
 import { DefaultContractType, ContractStorageType, ContractAbstraction } from './contract';
 import { InvalidDelegationSource, RevealOperationError } from './errors';
@@ -38,6 +39,7 @@ import {
   createTransferOperation,
   createTxRollupBatchOperation,
   createTransferTicketOperation,
+  createIncreasePaidStorageOperation,
 } from './prepare';
 import { smartContractAbstractionSemantic } from './semantic';
 import {
@@ -51,6 +53,8 @@ import { EstimationProvider } from '../estimate/estimate-provider-interface';
 import { TxRollupOriginationOperation } from '../operations/tx-rollup-origination-operation';
 import { TxRollupBatchOperation } from '../operations/tx-rollup-batch-operation';
 import { TransferTicketOperation } from '../operations/transfer-ticket-operation';
+import { IncreasePaidStorageOperation } from '../operations/increase-paid-storage-operation';
+
 export class RpcContractProvider
   extends OperationEmitter
   implements ContractProvider, StorageProvider
@@ -110,7 +114,7 @@ export class RpcContractProvider
 
     let contractSchema: Schema;
     if (Schema.isSchema(schema as Schema)) {
-      contractSchema = schema as Schema
+      contractSchema = schema as Schema;
     } else {
       contractSchema = Schema.fromRPCResponse({ script: schema as ScriptResponse });
     }
@@ -406,17 +410,20 @@ export class RpcContractProvider
     }
 
     const publicKeyHash = await this.signer.publicKeyHash();
-    const estimate = await this.estimate(params, this.estimator.transferTicket.bind(this.estimator));
+    const estimate = await this.estimate(
+      params,
+      this.estimator.transferTicket.bind(this.estimator)
+    );
     const operation = await createTransferTicketOperation({
       ...params,
       ...estimate,
     });
-    const source = params.source ?? publicKeyHash
+    const source = params.source ?? publicKeyHash;
     const ops = await this.addRevealOperationIfNeeded(operation, publicKeyHash);
-    const prepared = await this.prepareOperation({ operation: ops, source: params.source});
+    const prepared = await this.prepareOperation({ operation: ops, source: params.source });
     const opBytes = await this.forge(prepared);
     const { hash, context, forgedBytes, opResponse } = await this.signAndInject(opBytes);
-    return new TransferTicketOperation(hash, operation, source, forgedBytes, opResponse, context)
+    return new TransferTicketOperation(hash, operation, source, forgedBytes, opResponse, context);
   }
 
   /**
@@ -482,6 +489,38 @@ export class RpcContractProvider
     );
   }
 
+  /**
+   *
+   * @description Increase the paid storage of a smart contract
+   *
+   * @returns An operation handle with the result from the rpc node
+   *
+   * @param params increasePaidStorage operation parameter
+   */
+  async increasePaidStorage(params: IncreasePaidStorageParams) {
+    const publicKeyHash = await this.signer.publicKeyHash();
+    const estimate = await this.estimate(
+      params,
+      this.estimator.increasePaidStorage.bind(this.estimator)
+    );
+    const operation = await createIncreasePaidStorageOperation({
+      ...params,
+      ...estimate,
+    });
+    const ops = await this.addRevealOperationIfNeeded(operation, publicKeyHash);
+    const prepared = await this.prepareOperation({ operation: ops, source: publicKeyHash });
+    const opBytes = await this.forge(prepared);
+    const { hash, context, forgedBytes, opResponse } = await this.signAndInject(opBytes);
+    return new IncreasePaidStorageOperation(
+      hash,
+      operation,
+      publicKeyHash,
+      forgedBytes,
+      opResponse,
+      context
+    );
+  }
+
   /**
    *
    * @description Originate a new tx rollup. Will sign and inject an operation using the current context
diff --git a/packages/taquito/src/estimate/estimate-provider-interface.ts b/packages/taquito/src/estimate/estimate-provider-interface.ts
index 6f21e9e63..a5c64b7cd 100644
--- a/packages/taquito/src/estimate/estimate-provider-interface.ts
+++ b/packages/taquito/src/estimate/estimate-provider-interface.ts
@@ -11,6 +11,7 @@ import {
   TxRollupOriginateParams,
   TxRollupBatchParams,
   TransferTicketParams,
+  IncreasePaidStorageParams,
 } from '../operations/types';
 import { Estimate } from './estimate';
 
@@ -81,12 +82,22 @@ export interface EstimationProvider {
    *
    * @description Estimate gasLimit, storageLimit and fees for registering an expression (registerGlobalConstant operation)
    *
-   * @returns An estimation of gasLimit, storageLimit and fees for the operation or undefined if the account is already revealed
+   * @returns An estimation of gasLimit, storageLimit and fees for the operation
    *
    * @param params registerGlobalConstant operation parameter
    */
   registerGlobalConstant(params: RegisterGlobalConstantParams): Promise<Estimate>;
 
+  /**
+   *
+   * @description Estimate gasLimit, storageLimit and fees for an increase paid storage operation
+   *
+   * @returns An estimation of gasLimit, storageLimit, and fees for the operation
+   *
+   * @param Estimate
+   */
+  increasePaidStorage(params: IncreasePaidStorageParams): Promise<Estimate>;
+
   /**
    *
    * @description Estimate gasLimit, storageLimit and fees for a tx rollup origination operation
diff --git a/packages/taquito/src/estimate/rpc-estimate-provider.ts b/packages/taquito/src/estimate/rpc-estimate-provider.ts
index e31f8614a..660255b88 100644
--- a/packages/taquito/src/estimate/rpc-estimate-provider.ts
+++ b/packages/taquito/src/estimate/rpc-estimate-provider.ts
@@ -21,6 +21,7 @@ import {
   TxRollupOriginateParams,
   TxRollupBatchParams,
   TransferTicketParams,
+  IncreasePaidStorageParams,
 } from '../operations/types';
 import { Estimate, EstimateProperties } from './estimate';
 import { EstimationProvider } from '../estimate/estimate-provider-interface';
@@ -34,6 +35,7 @@ import {
   createTxRollupOriginationOperation,
   createTxRollupBatchOperation,
   createTransferTicketOperation,
+  createIncreasePaidStorageOperation,
 } from '../contract/prepare';
 import {
   validateAddress,
@@ -442,6 +444,14 @@ export class RPCEstimateProvider extends OperationEmitter implements EstimationP
             })
           );
           break;
+        case OpKind.INCREASE_PAID_STORAGE:
+          operations.push(
+            await createIncreasePaidStorageOperation({
+              ...param,
+              ...mergeLimits(param, DEFAULT_PARAMS),
+            })
+          );
+          break;
         default:
           throw new InvalidOperationKindError((params as any).kind);
       }
@@ -550,6 +560,37 @@ export class RPCEstimateProvider extends OperationEmitter implements EstimationP
     return Estimate.createEstimateInstanceFromProperties(estimateProperties);
   }
 
+  /**
+   *
+   * @description Estimate gasLimit, storageLimit, and fees for an increasePaidStorage operation
+   *
+   * @returns An estimation of gasLimit, storageLimit, and fees for the operation
+   *
+   * @param params increasePaidStorage operation parameters
+   */
+  async increasePaidStorage(params: IncreasePaidStorageParams) {
+    const { fee, storageLimit, gasLimit, ...rest } = params;
+    const pkh = (await this.getKeys()).publicKeyHash;
+
+    const protocolConstants = await this.context.readProvider.getProtocolConstants('head');
+    const DEFAULT_PARAMS = await this.getAccountLimits(pkh, protocolConstants);
+    const op = await createIncreasePaidStorageOperation({
+      ...rest,
+      ...mergeLimits({ fee, storageLimit, gasLimit }, DEFAULT_PARAMS),
+    });
+    const isRevealNeeded = await this.isRevealOpNeeded([op], pkh);
+    const ops = isRevealNeeded ? await this.addRevealOp([op], pkh) : op;
+    const estimateProperties = await this.prepareEstimate(
+      { operation: ops, source: pkh },
+      protocolConstants,
+      pkh
+    );
+    if (isRevealNeeded) {
+      estimateProperties.shift();
+    }
+    return Estimate.createEstimateInstanceFromProperties(estimateProperties);
+  }
+
   /**
    *
    * @description Estimate gasLimit, storageLimit and fees for a rollup origination operation
diff --git a/packages/taquito/src/operations/increase-paid-storage-operation.ts b/packages/taquito/src/operations/increase-paid-storage-operation.ts
new file mode 100644
index 000000000..eb255d21b
--- /dev/null
+++ b/packages/taquito/src/operations/increase-paid-storage-operation.ts
@@ -0,0 +1,80 @@
+import {
+  OperationContentsAndResult,
+  OperationContentsAndResultIncreasePaidStorage,
+} from '@taquito/rpc';
+import { Context } from '../context';
+import { Operation } from './operations';
+import {
+  FeeConsumingOperation,
+  ForgedBytes,
+  GasConsumingOperation,
+  RPCIncreasePaidStorageOperation,
+  StorageConsumingOperation,
+} from './types';
+
+/**
+ *
+ * @description IncreasePaidStorageOperation provides utility functions to fetch a new operation of kind increase_paid_storage
+ *
+ */
+
+export class IncreasePaidStorageOperation
+  extends Operation
+  implements GasConsumingOperation, StorageConsumingOperation, FeeConsumingOperation
+{
+  constructor(
+    hash: string,
+    private readonly params: RPCIncreasePaidStorageOperation,
+    public readonly source: string,
+    raw: ForgedBytes,
+    results: OperationContentsAndResult[],
+    context: Context
+  ) {
+    super(hash, raw, results, context);
+  }
+
+  get operationResults() {
+    const increasePaidStorageOp =
+      Array.isArray(this.results) &&
+      (this.results.find(
+        (op) => op.kind === 'increase_paid_storage'
+      ) as OperationContentsAndResultIncreasePaidStorage);
+    const result =
+      increasePaidStorageOp &&
+      increasePaidStorageOp.metadata &&
+      increasePaidStorageOp.metadata.operation_result;
+    return result ? result : undefined;
+  }
+
+  get status() {
+    return this.operationResults?.status ?? 'unknown';
+  }
+
+  get fee() {
+    return this.params.fee;
+  }
+
+  get gasLimit() {
+    return this.params.gas_limit;
+  }
+
+  get storageLimit() {
+    return this.params.storage_limit;
+  }
+
+  get errors() {
+    return this.operationResults?.errors;
+  }
+
+  get consumedMilliGas() {
+    return this.operationResults?.consumed_milligas;
+  }
+
+  get amount() {
+    return this.params.amount;
+  }
+
+  get destination() {
+    return this.params.destination;
+  }
+}
diff --git a/packages/taquito/src/operations/operation-emitter.ts b/packages/taquito/src/operations/operation-emitter.ts
index 5dce93daa..9f7459d97 100644
--- a/packages/taquito/src/operations/operation-emitter.ts
+++ b/packages/taquito/src/operations/operation-emitter.ts
@@ -159,8 +159,15 @@ export abstract class OperationEmitter {
               ticket_amount: `${op.ticket_amount}`,
               ...getSource(op),
               ...getFee(op),
+            };
+          case OpKind.INCREASE_PAID_STORAGE:
+            return {
+              ...op,
+              amount: `${op.amount}`,
+              ...getSource(op),
+              ...getFee(op),
+            };
 
-            }
           default:
             throw new InvalidOperationKindError((op as any).kind);
         }
diff --git a/packages/taquito/src/operations/types.ts b/packages/taquito/src/operations/types.ts
index 0f521986a..9f7de84b7 100644
--- a/packages/taquito/src/operations/types.ts
+++ b/packages/taquito/src/operations/types.ts
@@ -16,6 +16,7 @@ export type ParamsWithKind =
   | withKind<TransferParams, OpKind.TRANSACTION>
   | withKind<ActivationParams, OpKind.ACTIVATION>
   | withKind<RegisterGlobalConstantParams, OpKind.REGISTER_GLOBAL_CONSTANT>
+  | withKind<IncreasePaidStorageParams, OpKind.INCREASE_PAID_STORAGE>
   | withKind<TxRollupOriginateParams, OpKind.TX_ROLLUP_ORIGINATION>
   | withKind<TxRollupBatchParams, OpKind.TX_ROLLUP_SUBMIT_BATCH>
   | withKind<TransferTicketParams, OpKind.TRANSFER_TICKET>;
@@ -52,6 +53,7 @@ export type RPCOpWithFee =
   | RPCDelegateOperation
   | RPCRevealOperation
   | RPCRegisterGlobalConstantOperation
+  | RPCIncreasePaidStorageOperation
   | RPCTxRollupOriginationOperation
   | RPCTxRollupBatchOperation
   | RPCTransferTicketOperation;
@@ -61,6 +63,7 @@ export type RPCOpWithSource =
   | RPCDelegateOperation
   | RPCRevealOperation
   | RPCRegisterGlobalConstantOperation
+  | RPCIncreasePaidStorageOperation
   | RPCTxRollupOriginationOperation
   | RPCTxRollupBatchOperation
   | RPCTransferTicketOperation;
@@ -75,6 +78,7 @@ export const isOpWithFee = <T extends { kind: OpKind }>(
       'origination',
       'reveal',
       'register_global_constant',
+      'increase_paid_storage',
       'tx_rollup_origination',
       'tx_rollup_submit_batch',
       'transfer_ticket',
@@ -91,6 +95,7 @@ export const isOpRequireReveal = <T extends { kind: OpKind }>(
       'delegation',
       'origination',
       'register_global_constant',
+      'increase_paid_storage',
       'tx_rollup_origination',
       'tx_rollup_submit_batch',
       'transfer_ticket',
@@ -337,6 +342,18 @@ export interface TxRollupOriginateParams {
   storageLimit?: number;
 }
 
+/**
+ * @description Parameters for the `txRollupSubmitBatch` method
+ */
+export interface TxRollupBatchParams {
+  source?: string;
+  fee?: number;
+  gasLimit?: number;
+  storageLimit?: number;
+  rollup: string;
+  content: string;
+}
+
 /**
  * @description RPC tx rollup batch operation
  */
@@ -384,15 +401,28 @@ export interface RPCTransferTicketOperation {
 }
 
 /**
- * @description Parameters for the `txRollupSubmitBatch` method
+ * @description Parameters for the increasePaidStorage method
  */
-export interface TxRollupBatchParams {
+export interface IncreasePaidStorageParams {
   source?: string;
   fee?: number;
   gasLimit?: number;
   storageLimit?: number;
-  rollup: string;
-  content: string;
+  amount: number;
+  destination: string;
+}
+
+/**
+ * @description RPC IncreasePaidStorage operation
+ */
+export interface RPCIncreasePaidStorageOperation {
+  kind: OpKind.INCREASE_PAID_STORAGE;
+  source: string;
+  fee: number;
+  gas_limit: number;
+  storage_limit: number;
+  amount: number;
+  destination: string;
 }
 
 export type RPCOperation =
@@ -404,7 +434,8 @@ export type RPCOperation =
   | RPCRegisterGlobalConstantOperation
   | RPCTxRollupOriginationOperation
   | RPCTxRollupBatchOperation
-  | RPCTransferTicketOperation;
+  | RPCTransferTicketOperation
+  | RPCIncreasePaidStorageOperation;
 
 export type PrepareOperationParams = {
   operation: RPCOperation | RPCOperation[];
diff --git a/website/sidebars.js b/website/sidebars.js
index 229516b28..0bc66af6d 100644
--- a/website/sidebars.js
+++ b/website/sidebars.js
@@ -37,6 +37,7 @@ const sidebars = {
         'maps_bigmaps',
         'michelsonmap',
         'originate',
+        'increase_paid_storage',
         'global_constant',
         'rpc_nodes',
         'rpc_package',


Test patch:
diff --git a/integration-tests/contract-increase-paid-storage-operation.spec.ts b/integration-tests/contract-increase-paid-storage-operation.spec.ts
new file mode 100644
index 000000000..e947cc594
--- /dev/null
+++ b/integration-tests/contract-increase-paid-storage-operation.spec.ts
@@ -0,0 +1,82 @@
+import { CONFIGS } from './config';
+import { OpKind, Protocols } from '@taquito/taquito';
+import { ligoSample } from './data/ligo-simple-contract';
+
+CONFIGS().forEach(({ lib, rpc, setup, protocol, knownContract }) => {
+  const kathmandunet = (protocol === Protocols.PtKathman) ? it : it.skip;
+  const Tezos = lib;
+
+  describe(`Test Increase Paid Storage using: ${rpc}`, () => {
+    beforeEach(async (done) => {
+      await setup(true);
+      done();
+    });
+
+    kathmandunet('should be able to increase the paid storage of a contract successfully', async (done) => {
+      const op = await Tezos.contract.increasePaidStorage({
+        amount: 1,
+        destination: knownContract
+      });
+
+      await op.confirmation();
+      expect(op.hash).toBeDefined();
+      expect(op.status).toEqual('applied');
+      done();
+    });
+
+    kathmandunet('should be able to include increasePaidStorage operation in a batch', async (done) => {
+      const op = await Tezos.contract
+        .batch()
+        .withOrigination({
+          balance: "1",
+          code: `parameter string;
+          storage string;
+          code {CAR;
+                PUSH string "Hello ";
+                CONCAT;
+                NIL operation; PAIR};
+          `,
+          init: `"test"`
+        })
+        .withIncreasePaidStorage({
+          amount: 1,
+          destination: knownContract
+        })
+        .send();
+      await op.confirmation();
+      expect(op.status).toEqual('applied');
+      done();
+    });
+
+    kathmandunet('should be able to include increasePaidStorage operation in a batch (different batch syntax)', async (done) => {
+      const op = await Tezos.contract.batch([
+        {
+          kind: OpKind.ORIGINATION, 
+          balance: '1', 
+          code: ligoSample, 
+          storage: 0 
+        },
+        { 
+          kind: OpKind.INCREASE_PAID_STORAGE,
+          amount: 1, 
+          destination: knownContract 
+        } 
+      ])
+      .send();
+
+      await op.confirmation();
+      expect(op.status).toEqual('applied');
+      done();
+    });
+
+    kathmandunet('should return error when destination contract address is invalid', async (done) => {
+      expect(async () => {
+        const op = await Tezos.contract.increasePaidStorage({
+          amount: 1,
+          destination: 'invalid_address'
+        });
+      }).rejects.toThrow();
+      done();
+    });
+  });
+});
\ No newline at end of file
diff --git a/packages/taquito-michel-codec/test/contracts_014.spec.ts b/packages/taquito-michel-codec/test/contracts_014.spec.ts
new file mode 100644
index 000000000..3e5804042
--- /dev/null
+++ b/packages/taquito-michel-codec/test/contracts_014.spec.ts
@@ -0,0 +1,57 @@
+import fs from 'fs';
+import path from 'path';
+import { inspect } from 'util';
+import { Contract, ContractOptions } from '../src/michelson-contract';
+import { Protocol } from '../src/michelson-types';
+import { MichelsonError } from '../src/utils';
+
+const contracts: {
+  [group: string]: string[];
+} = {
+  entrypoints: [
+
+  ],
+  ill_typed: [
+    'emit_instruction_error_contract.tz',
+  ],
+  lib_protocol: [
+  ],
+  macros: [
+  ],
+  mini_scenarios: [
+  ],
+  opcodes: [
+    'emit_instruction.tz',
+    'emit_instruction_event.tz',
+  ]
+};
+
+describe('PtKathmandu', () => {
+  for (const [group, list] of Object.entries(contracts)) {
+    describe(group, () => {
+      for (const contract of list) {
+        it(contract, () => {
+          const options: ContractOptions = {
+            protocol: Protocol.PtKathman,
+          };
+
+          const filename = path.resolve(__dirname, 'contracts_014', group, contract);
+          const src = fs.readFileSync(filename).toString();
+          if (group === 'ill_typed') {
+            expect(() => Contract.parse(src, options)).toThrow();
+            return;
+          }
+
+          try {
+            Contract.parse(src, options);
+          } catch (err) {
+            if (err instanceof MichelsonError) {
+              console.log(inspect(err, false, null));
+            }
+            throw err;
+          }
+        });
+      }
+    });
+  }
+});
diff --git a/packages/taquito-michel-codec/test/contracts_014/ill_typed/emit_instruction_error_contract.tz b/packages/taquito-michel-codec/test/contracts_014/ill_typed/emit_instruction_error_contract.tz
new file mode 100644
index 000000000..91bb320a0
--- /dev/null
+++ b/packages/taquito-michel-codec/test/contracts_014/ill_typed/emit_instruction_error_contract.tz
@@ -0,0 +1,16 @@
+{ parameter unit ;
+  storage unit ;
+  code { DROP ;
+         UNIT ;
+         PUSH nat 10 ;
+         LEFT string ;
+         EMIT %event ;
+         PUSH string "lorem ipsum" ;
+         RIGHT nat ;
+         EMIT %event (or (string %words) (string %words)) ;
+         NIL operation ;
+         SWAP ;
+         CONS ;
+         SWAP ;
+         CONS ;
+         PAIR } }
diff --git a/packages/taquito-michel-codec/test/contracts_014/opcodes/emit_instruction.tz b/packages/taquito-michel-codec/test/contracts_014/opcodes/emit_instruction.tz
new file mode 100644
index 000000000..c8c2da088
--- /dev/null
+++ b/packages/taquito-michel-codec/test/contracts_014/opcodes/emit_instruction.tz
@@ -0,0 +1,16 @@
+parameter unit;
+storage unit;
+code { DROP ;
+       UNIT ;
+       PUSH string "right" ;
+       RIGHT nat ;
+       EMIT %tag1 ;
+       PUSH nat 2 ;
+       LEFT string ;
+       EMIT %tag2 (or (nat %int) (string %str)) ;
+       NIL operation ;
+       SWAP ;
+       CONS ;
+       SWAP ;
+       CONS ;
+       PAIR }
diff --git a/packages/taquito-michel-codec/test/contracts_014/opcodes/emit_instruction_event.tz b/packages/taquito-michel-codec/test/contracts_014/opcodes/emit_instruction_event.tz
new file mode 100644
index 000000000..1d4c5a75f
--- /dev/null
+++ b/packages/taquito-michel-codec/test/contracts_014/opcodes/emit_instruction_event.tz
@@ -0,0 +1,16 @@
+{ parameter unit ;
+  storage unit ;
+  code { DROP ;
+         UNIT ;
+         PUSH nat 10 ;
+         LEFT string ;
+         EMIT %event ;
+         PUSH string "lorem ipsum" ;
+         RIGHT nat ;
+         EMIT %event (or (nat %number) (string %words)) ;
+         NIL operation ;
+         SWAP ;
+         CONS ;
+         SWAP ;
+         CONS ;
+         PAIR } }
diff --git a/packages/taquito-rpc/test/data/rpc-responses.ts b/packages/taquito-rpc/test/data/rpc-responses.ts
index 3f43ad4f9..674fd1e6b 100644
--- a/packages/taquito-rpc/test/data/rpc-responses.ts
+++ b/packages/taquito-rpc/test/data/rpc-responses.ts
@@ -2497,6 +2497,19 @@ export const delegatesIthacanetSample = {
   voting_power: 199,
 };
 
+export const delegatesKathmandunetSample = {
+  full_balance: '965532868030',
+  current_frozen_deposits: '96350095609',
+  frozen_deposits: '96350095609',
+  staking_balance: '970221941952',
+  delegated_contracts: ['tz1cjyja1TU6fiyiFav3mFAdnDsCReJ12hPD'],
+  delegated_balance: '4689073922',
+  deactivated: false,
+  grace_period: 42,
+  voting_power: '968128693450',
+  remaining_proposals: 20,
+};
+
 export const blockIthacanetSample = {
   protocol: 'Psithaca2MLRFYargivpo7YvUr7wUDqyxrdhC5CQq78mRvimz6A',
   chain_id: 'NetXnHfVqm9iesp',
@@ -4654,6 +4667,112 @@ export const blockKathmandunetSample = {
         signature:
           'sigdUXgzV3FcbhV7qUAYGCbV86xZEpcBq1S3Acng974GvG8rULLnoNkXn1dvKvfbfvz3zChYCpjcDmR8f1shjAg1uSksceRp',
       },
+      {
+        protocol: 'PtKathmankSpLLDALzWw7CGD2j2MtyveTwboEYokqUCP4a1LxMg',
+        chain_id: 'NetXi2ZagzEsXbZ',
+        hash: 'oorMQ4cCHReHtUdyEqpWBjyAgu59AWYMzSP5bSwi2gSGGHBSLF5',
+        branch: 'BKuq9qvyUfiZH64z7J7nxKAt7HGA1m2rgiR24XrCsAEgBh2JJd1',
+        contents: [
+          {
+            kind: 'transaction',
+            source: 'tz1ejWMc4oNPuYJcs2UBFALuzQy3jKcZxEwL',
+            fee: '673',
+            counter: '84777',
+            gas_limit: '4224',
+            storage_limit: '0',
+            amount: '0',
+            destination: 'KT1D7mKRckD2ZoWGcGtUvBpDxb48WxpnLu1Q',
+            metadata: {
+              balance_updates: [
+                {
+                  kind: 'contract',
+                  contract: 'tz1ejWMc4oNPuYJcs2UBFALuzQy3jKcZxEwL',
+                  change: '-673',
+                  origin: 'block',
+                },
+                {
+                  kind: 'accumulator',
+                  category: 'block fees',
+                  change: '673',
+                  origin: 'block',
+                },
+              ],
+              operation_result: {
+                status: 'applied',
+                storage: {
+                  prim: 'Unit',
+                },
+                consumed_milligas: '2123011',
+                storage_size: '133',
+              },
+              internal_operation_results: [
+                {
+                  kind: 'event',
+                  source: 'KT1D7mKRckD2ZoWGcGtUvBpDxb48WxpnLu1Q',
+                  nonce: 0,
+                  type: {
+                    prim: 'or',
+                    args: [
+                      {
+                        prim: 'nat',
+                      },
+                      {
+                        prim: 'string',
+                      },
+                    ],
+                  },
+                  tag: 'event',
+                  payload: {
+                    prim: 'Left',
+                    args: [
+                      {
+                        int: '10',
+                      },
+                    ],
+                  },
+                  result: {
+                    status: 'applied',
+                    consumed_milligas: '1000000',
+                  },
+                },
+                {
+                  kind: 'event',
+                  source: 'KT1D7mKRckD2ZoWGcGtUvBpDxb48WxpnLu1Q',
+                  nonce: 1,
+                  type: {
+                    prim: 'or',
+                    args: [
+                      {
+                        prim: 'nat',
+                        annots: ['%number'],
+                      },
+                      {
+                        prim: 'string',
+                        annots: ['%words'],
+                      },
+                    ],
+                  },
+                  tag: 'event',
+                  payload: {
+                    prim: 'Right',
+                    args: [
+                      {
+                        string: 'lorem ipsum',
+                      },
+                    ],
+                  },
+                  result: {
+                    status: 'applied',
+                    consumed_milligas: '1000000',
+                  },
+                },
+              ],
+            },
+          },
+        ],
+        signature:
+          'sigfSTrupvjTWBW4NNXJHLyNEd6gUuD3Jzm9YZzSrH82X3somYZPpgCayRTkzmk1NwxGQCKJHLGsv7xxhVNKsgtxTqF8FEqe',
+      },
     ],
   ],
 };
diff --git a/packages/taquito-rpc/test/taquito-rpc.spec.ts b/packages/taquito-rpc/test/taquito-rpc.spec.ts
index cd7283bae..03d6d9747 100644
--- a/packages/taquito-rpc/test/taquito-rpc.spec.ts
+++ b/packages/taquito-rpc/test/taquito-rpc.spec.ts
@@ -1,3 +1,4 @@
+/* eslint-disable @typescript-eslint/no-explicit-any */
 /* eslint-disable @typescript-eslint/no-non-null-assertion */
 import { OpKind, RpcClient } from '../src/taquito-rpc';
 import BigNumber from 'bignumber.js';
@@ -25,12 +26,14 @@ import {
   Inode,
   OtherElts,
   OperationContentsAndResultIncreasePaidStorage,
+  OperationResultEvent,
 } from '../src/types';
 import {
   blockIthacanetSample,
   blockJakartanetSample,
   blockKathmandunetSample,
   delegatesIthacanetSample,
+  delegatesKathmandunetSample,
 } from './data/rpc-responses';
 
 /**
@@ -92,7 +95,7 @@ describe('RpcClient test', () => {
   });
 
   describe('getBalance', () => {
-    it('query the right url and return a string', async (done) => {
+    it('should query the right url and return a string', async (done) => {
       httpBackend.createRequest.mockReturnValue(Promise.resolve('10000'));
       const balance = await client.getBalance(contractAddress);
 
@@ -108,7 +111,7 @@ describe('RpcClient test', () => {
   });
 
   describe('getStorage', () => {
-    it('query the right url', async (done) => {
+    it('should query the right url', async (done) => {
       await client.getStorage(contractAddress);
 
       expect(httpBackend.createRequest.mock.calls[0][0]).toEqual({
@@ -121,7 +124,7 @@ describe('RpcClient test', () => {
   });
 
   describe('getScript', () => {
-    it('query the right url', async (done) => {
+    it('should query the right url', async (done) => {
       await client.getScript(contractAddress);
 
       expect(httpBackend.createRequest.mock.calls[0][0]).toEqual({
@@ -134,7 +137,7 @@ describe('RpcClient test', () => {
   });
 
   describe('getNormalizedScript', () => {
-    it('query the right url', async (done) => {
+    it('should query the right url', async (done) => {
       await client.getNormalizedScript(contractAddress);
 
       expect(httpBackend.createRequest.mock.calls[0][0]).toEqual({
@@ -148,7 +151,7 @@ describe('RpcClient test', () => {
   });
 
   describe('getContract', () => {
-    it('query the right url', async (done) => {
+    it('should query the right url', async (done) => {
       httpBackend.createRequest.mockResolvedValue({ balance: '10000' });
       const response = await client.getContract(contractAddress);
 
@@ -165,7 +168,7 @@ describe('RpcClient test', () => {
   });
 
   describe('getManagerKey', () => {
-    it('query the right url', async (done) => {
+    it('should query the right url', async (done) => {
       await client.getManagerKey(contractAddress);
 
       expect(httpBackend.createRequest.mock.calls[0][0]).toEqual({
@@ -178,7 +181,7 @@ describe('RpcClient test', () => {
   });
 
   describe('getDelegate', () => {
-    it('query the right url', async (done) => {
+    it('should query the right url', async (done) => {
       await client.getDelegate(contractAddress);
 
       expect(httpBackend.createRequest.mock.calls[0][0]).toEqual({
@@ -191,7 +194,7 @@ describe('RpcClient test', () => {
   });
 
   describe('getBlockHash', () => {
-    it('query the right url', async (done) => {
+    it('should query the right url', async (done) => {
       await client.getBlockHash();
 
       expect(httpBackend.createRequest.mock.calls[0][0]).toEqual({
@@ -221,7 +224,7 @@ describe('RpcClient test', () => {
       grace_period: 146,
     };
 
-    it('query the right url', async (done) => {
+    it('should query the right url', async (done) => {
       httpBackend.createRequest.mockResolvedValue(sampleResponse);
       await client.getDelegates(contractAddress);
 
@@ -233,7 +236,7 @@ describe('RpcClient test', () => {
       done();
     });
 
-    it('parse the response properly', async (done) => {
+    it('should parse the response properly', async (done) => {
       httpBackend.createRequest.mockResolvedValue(sampleResponse);
       const response = await client.getDelegates(contractAddress);
 
@@ -267,7 +270,7 @@ describe('RpcClient test', () => {
       done();
     });
 
-    it('parse the response properly, proto10', async (done) => {
+    it('should parse the response properly, proto10', async (done) => {
       // deposit replaced by deposits
       httpBackend.createRequest.mockResolvedValue({
         balance: '5976016544884',
@@ -313,7 +316,7 @@ describe('RpcClient test', () => {
       done();
     });
 
-    it('parse the response properly, proto12', async (done) => {
+    it('should parse the response properly, proto12', async (done) => {
       httpBackend.createRequest.mockResolvedValue(delegatesIthacanetSample);
       const response = await client.getDelegates(contractAddress);
 
@@ -331,10 +334,30 @@ describe('RpcClient test', () => {
 
       done();
     });
+
+    it('should parse the response properly, proto14', async (done) => {
+      httpBackend.createRequest.mockResolvedValue(delegatesKathmandunetSample);
+      const response = await client.getDelegates(contractAddress);
+
+      expect(response).toEqual({
+        full_balance: new BigNumber('965532868030'),
+        current_frozen_deposits: new BigNumber('96350095609'),
+        frozen_deposits: new BigNumber('96350095609'),
+        staking_balance: new BigNumber('970221941952'),
+        delegated_contracts: ['tz1cjyja1TU6fiyiFav3mFAdnDsCReJ12hPD'],
+        delegated_balance: new BigNumber('4689073922'),
+        deactivated: false,
+        grace_period: 42,
+        voting_power: new BigNumber(968128693450),
+        remaining_proposals: 20,
+      });
+
+      done();
+    });
   });
 
   describe('getBigMapKey', () => {
-    it('query the right url', async (done) => {
+    it('should query the right url', async (done) => {
       await client.getBigMapKey(contractAddress, { key: 'test', type: 'string' } as any);
       expect(httpBackend.createRequest.mock.calls[0][0]).toEqual({
         method: 'POST',
@@ -348,7 +371,7 @@ describe('RpcClient test', () => {
   });
 
   describe('forgeOperation', () => {
-    it('query the right url', async (done) => {
+    it('should query the right url', async (done) => {
       await client.forgeOperations({} as any);
       expect(httpBackend.createRequest.mock.calls[0][0]).toEqual({
         method: 'POST',
@@ -362,7 +385,7 @@ describe('RpcClient test', () => {
   });
 
   describe('injectOperations', () => {
-    it('query the right url', async (done) => {
+    it('should query the right url', async (done) => {
       await client.injectOperation({} as any);
       expect(httpBackend.createRequest.mock.calls[0][0]).toEqual({
         method: 'POST',
@@ -376,7 +399,7 @@ describe('RpcClient test', () => {
   });
 
   describe('preapplyOperations', () => {
-    it('query the right url', async (done) => {
+    it('should query the right url', async (done) => {
       httpBackend.createRequest.mockResolvedValue({});
       await client.preapplyOperations({} as any);
       expect(httpBackend.createRequest.mock.calls[0][0]).toEqual({
@@ -391,7 +414,7 @@ describe('RpcClient test', () => {
   });
 
   describe('getBlockHeader', () => {
-    it('query the right url', async (done) => {
+    it('should query the right url', async (done) => {
       const sampleResponse = {
         protocol: 'Pt24m4xiPbLDhVgVfABUjirbmda3yohdN82Sp9FeuAXJ4eV9otd',
         chain_id: 'NetXdQprcVkpaWU',
@@ -440,7 +463,7 @@ describe('RpcClient test', () => {
   });
 
   describe('getBlockMetadata', () => {
-    it('query the right url', async (done) => {
+    it('should query the right url', async (done) => {
       const sampleResponse = {
         protocol: 'Pt24m4xiPbLDhVgVfABUjirbmda3yohdN82Sp9FeuAXJ4eV9otd',
         next_protocol: 'Pt24m4xiPbLDhVgVfABUjirbmda3yohdN82Sp9FeuAXJ4eV9otd',
@@ -565,7 +588,7 @@ describe('RpcClient test', () => {
   });
 
   describe('getConstants Proto014', () => {
-    it('query the right url and casts relevant properties to BigNumber', async (done) => {
+    it('should query the right url and casts relevant properties to BigNumber', async (done) => {
       httpBackend.createRequest.mockResolvedValue({
         proof_of_work_nonce_size: 8,
         nonce_length: 32,
@@ -752,7 +775,7 @@ describe('RpcClient test', () => {
   });
 
   describe('getConstants Proto012', () => {
-    it('query the right url and casts property to BigNumber', async (done) => {
+    it('should query the right url and casts property to BigNumber', async (done) => {
       httpBackend.createRequest.mockReturnValue(
         Promise.resolve({
           proof_of_work_nonce_size: 8,
@@ -860,7 +883,7 @@ describe('RpcClient test', () => {
   });
 
   describe('getConstants Proto007', () => {
-    it('query the right url and casts property to BigNumber', async (done) => {
+    it('should query the right url and casts property to BigNumber', async (done) => {
       httpBackend.createRequest.mockReturnValue(
         Promise.resolve({
           proof_of_work_nonce_size: 8,
@@ -935,7 +958,7 @@ describe('RpcClient test', () => {
   });
 
   describe('getConstants Proto006', () => {
-    it('properties return by the RPC are accessible and the ones that do not belong to proto6 are undefined', async (done) => {
+    it('should properties return by the RPC are accessible and the ones that do not belong to proto6 are undefined', async (done) => {
       httpBackend.createRequest.mockReturnValue(
         Promise.resolve({
           proof_of_work_nonce_size: 8,
@@ -991,7 +1014,7 @@ describe('RpcClient test', () => {
   });
 
   describe('getConstants Proto005', () => {
-    it('properties return by the RPC are accessible and the ones that do not belong to proto5 are undefined', async (done) => {
+    it('should properties return by the RPC are accessible and the ones that do not belong to proto5 are undefined', async (done) => {
       httpBackend.createRequest.mockReturnValue(
         Promise.resolve({
           proof_of_work_nonce_size: 8,
@@ -1057,7 +1080,7 @@ describe('RpcClient test', () => {
   });
 
   describe('getBlock', () => {
-    it('query the right url and property for endorsement', async (done) => {
+    it('should query the right url and property for endorsement', async (done) => {
       httpBackend.createRequest.mockReturnValue(
         Promise.resolve({
           protocol: 'Pt24m4xiPbLDhVgVfABUjirbmda3yohdN82Sp9FeuAXJ4eV9otd',
@@ -1198,7 +1221,7 @@ describe('RpcClient test', () => {
   });
 
   describe('getBlock', () => {
-    it('query the right url and property for operation', async (done) => {
+    it('should query the right url and property for operation', async (done) => {
       httpBackend.createRequest.mockReturnValue(
         Promise.resolve({
           protocol: 'PtEdo2ZkT9oKpimTah6x2embF25oss54njMuPzkJTEi5RqfdZFA',
@@ -1441,7 +1464,7 @@ describe('RpcClient test', () => {
       done();
     });
 
-    it('query the right url and property for operation, proto 9, endorsement_with_slot', async (done) => {
+    it('should query the right url and property for operation, proto 9, endorsement_with_slot', async (done) => {
       httpBackend.createRequest.mockReturnValue(
         Promise.resolve({
           protocol: 'PsFLorenaUUuikDWvMDr6fGBRG8kt3e3D3fHoXK1j1BFRxeSH4i',
@@ -1529,7 +1552,7 @@ describe('RpcClient test', () => {
       done();
     });
 
-    it('query the right url and properties (big_map_diff and lazy_storage_diff) in transaction operation result, proto 9', async (done) => {
+    it('should query the right url and properties (big_map_diff and lazy_storage_diff) in transaction operation result, proto 9', async (done) => {
       httpBackend.createRequest.mockReturnValue(
         Promise.resolve({
           protocol: 'PsFLorenaUUuikDWvMDr6fGBRG8kt3e3D3fHoXK1j1BFRxeSH4i',
@@ -2131,7 +2154,7 @@ describe('RpcClient test', () => {
       done();
     });
 
-    it('query the right url and properties (lazy_storage_diff of kind sapling_state) in transaction operation result, proto 8', async (done) => {
+    it('should query the right url and properties (lazy_storage_diff of kind sapling_state) in transaction operation result, proto 8', async (done) => {
       httpBackend.createRequest.mockReturnValue(
         Promise.resolve({
           protocol: 'PtEdo2ZkT9oKpimTah6x2embF25oss54njMuPzkJTEi5RqfdZFA',
@@ -2243,7 +2266,7 @@ describe('RpcClient test', () => {
       done();
     });
 
-    it('Access new properties "liquidity_baking_escape_ema", "implicit_operations_results" and "subsidy" in block metadata, proto 10', async (done) => {
+    it('should access new properties "liquidity_baking_escape_ema", "implicit_operations_results" and "subsidy" in block metadata, proto 10', async (done) => {
       httpBackend.createRequest.mockReturnValue(
         Promise.resolve({
           protocol: 'PtGRANADsDU8R9daYKAgWnQYAJ64omN1o3KMGVCykShA97vQbvV',
@@ -2368,7 +2391,7 @@ describe('RpcClient test', () => {
       done();
     });
 
-    it('fetches a block having a RegisterGlobalConstant operation and it validates its properties, proto 11', async (done) => {
+    it('should fetch a block having a RegisterGlobalConstant operation and it validates its properties, proto 11', async (done) => {
       httpBackend.createRequest.mockReturnValue(
         Promise.resolve({
           protocol: 'PtHangzHogokSuiMHemCuowEavgYTP8J5qQ9fQS793MHYFpCY3r',
@@ -3026,6 +3049,54 @@ describe('RpcClient test', () => {
       expect(content.metadata.operation_result.consumed_milligas).toEqual('1000000');
       done();
     });
+
+    it('should be able to access the properties of internal operation type event, proto14', async (done) => {
+      httpBackend.createRequest.mockReturnValue(Promise.resolve(blockKathmandunetSample));
+
+      const response = await client.getBlock();
+      const content = response.operations[3][1]
+        .contents[0] as OperationContentsAndResultTransaction;
+
+      expect(content.metadata.internal_operation_results).toBeDefined();
+      expect(content.metadata.internal_operation_results![0].kind).toEqual(OpKind.EVENT);
+      expect(content.metadata.internal_operation_results![0].source).toEqual(
+        'KT1D7mKRckD2ZoWGcGtUvBpDxb48WxpnLu1Q'
+      );
+      expect(content.metadata.internal_operation_results![0].nonce).toEqual(0);
+
+      expect(content.metadata.internal_operation_results![0].amount).toBeUndefined();
+      expect(content.metadata.internal_operation_results![0].destination).toBeUndefined();
+      expect(content.metadata.internal_operation_results![0].parameters).toBeUndefined();
+      expect(content.metadata.internal_operation_results![0].public_key).toBeUndefined();
+      expect(content.metadata.internal_operation_results![0].balance).toBeUndefined();
+      expect(content.metadata.internal_operation_results![0].delegate).toBeUndefined();
+      expect(content.metadata.internal_operation_results![0].value).toBeUndefined();
+      expect(content.metadata.internal_operation_results![0].limit).toBeUndefined();
+      expect(content.metadata.internal_operation_results![0].script).toBeUndefined();
+
+      expect(content.metadata.internal_operation_results![0].type).toBeDefined();
+      expect(content.metadata.internal_operation_results![0].type).toEqual({
+        prim: 'or',
+        args: [{ prim: 'nat' }, { prim: 'string' }],
+      });
+      expect(content.metadata.internal_operation_results![0].tag).toBeDefined();
+      expect(content.metadata.internal_operation_results![0].tag).toEqual('event');
+      expect(content.metadata.internal_operation_results![0].payload).toBeDefined();
+      expect(content.metadata.internal_operation_results![0].payload).toEqual({
+        prim: 'Left',
+        args: [{ int: '10' }],
+      });
+      expect(content.metadata.internal_operation_results![0].result).toBeDefined();
+
+      const internalResult = content.metadata.internal_operation_results![0]
+        .result as OperationResultEvent;
+      expect(internalResult.status).toEqual('applied');
+      expect(internalResult.consumed_milligas).toBeDefined();
+      expect(internalResult.consumed_milligas).toEqual('1000000');
+      expect(internalResult.errors).toBeUndefined();
+
+      done();
+    });
   });
 
   describe('getBakingRights', () => {
@@ -3109,7 +3180,7 @@ describe('RpcClient test', () => {
   });
 
   describe('getBallotList', () => {
-    it('query the right url and data', async (done) => {
+    it('should query the right url and data', async (done) => {
       httpBackend.createRequest.mockReturnValue(
         Promise.resolve([
           {
@@ -3151,7 +3222,7 @@ describe('RpcClient test', () => {
   });
 
   describe('getBallots', () => {
-    it('query the right url and data', async (done) => {
+    it('should query the right url and data', async (done) => {
       httpBackend.createRequest.mockReturnValue(Promise.resolve({ yay: 5943, nay: 0, pass: 0 }));
       const response = await client.getBallots();
 
@@ -3166,7 +3237,7 @@ describe('RpcClient test', () => {
   });
 
   describe('getCurrentProposal', () => {
-    it('query the right url and data', async (done) => {
+    it('should query the right url and data', async (done) => {
       httpBackend.createRequest.mockReturnValue(
         Promise.resolve('PsBABY5HQTSkA4297zNHfsZNKtxULfL18y95qb3m53QJiXGmrbU')
       );
@@ -3183,7 +3254,7 @@ describe('RpcClient test', () => {
   });
 
   describe('getCurrentQuorum', () => {
-    it('query the right url and data', async (done) => {
+    it('should query the right url and data', async (done) => {
       httpBackend.createRequest.mockReturnValue(Promise.resolve(7291));
       const response = await client.getCurrentQuorum();
 
@@ -3198,7 +3269,7 @@ describe('RpcClient test', () => {
   });
 
   describe('getVotesListings', () => {
-    it('query the right url and data', async (done) => {
+    it('should query the right url and data', async (done) => {
       httpBackend.createRequest.mockReturnValue(
         Promise.resolve([
           {
@@ -3259,7 +3330,7 @@ describe('RpcClient test', () => {
   });
 
   describe('getProposals', () => {
-    it('query the right url and data', async (done) => {
+    it('should query the right url and data', async (done) => {
       httpBackend.createRequest.mockReturnValue(
         Promise.resolve([
           ['PsBABY5HQTSkA4297zNHfsZNKtxULfL18y95qb3m53QJiXGmrbU', 2832],
@@ -3279,7 +3350,7 @@ describe('RpcClient test', () => {
   });
 
   describe('getEntrypoints', () => {
-    it('query the right url and data', async (done) => {
+    it('should query the right url and data', async (done) => {
       httpBackend.createRequest.mockReturnValue({ entrypoints: {} });
       const response = await client.getEntrypoints(contractAddress);
 
@@ -3293,7 +3364,7 @@ describe('RpcClient test', () => {
   });
 
   describe('runOperation', () => {
-    it('query the right url and data', async (done) => {
+    it('should query the right url and data', async (done) => {
       const testData = {};
 
       httpBackend.createRequest.mockResolvedValue({ content: {} });
@@ -3353,7 +3424,7 @@ describe('RpcClient test', () => {
   });
 
   describe('runView', () => {
-    it('query the right url and data', async (done) => {
+    it('should query the right url and data', async (done) => {
       const testData: RPCRunViewParam = {
         contract: 'test',
         entrypoint: 'test',
@@ -3381,7 +3452,7 @@ describe('RpcClient test', () => {
       done();
     });
 
-    it('query the right url and data with unparsing_mode overriden', async (done) => {
+    it('should query the right url and data with unparsing_mode overriden', async (done) => {
       const testData: RPCRunViewParam = {
         contract: 'test',
         entrypoint: 'test',
@@ -3404,7 +3475,7 @@ describe('RpcClient test', () => {
   });
 
   describe('packData', () => {
-    it('query the right url and data', async (done) => {
+    it('should query the right url and data', async (done) => {
       httpBackend.createRequest.mockResolvedValue({ packed: 'cafe', gas: 'unaccounted' });
       const response = await client.packData({
         data: { string: 'test' },
@@ -3420,7 +3491,7 @@ describe('RpcClient test', () => {
       done();
     });
 
-    it('return a big number for gas when it is a big number', async (done) => {
+    it('should return a big number for gas when it is a big number', async (done) => {
       httpBackend.createRequest.mockResolvedValue({ packed: 'cafe', gas: '2' });
       const response = await client.packData({
         data: { string: 'test' },
@@ -3432,7 +3503,7 @@ describe('RpcClient test', () => {
       done();
     });
 
-    it('return undefined for gas when it is missing', async (done) => {
+    it('should return undefined for gas when it is missing', async (done) => {
       httpBackend.createRequest.mockResolvedValue({ packed: 'cafe' });
       const response = await client.packData({
         data: { string: 'test' },
@@ -3445,7 +3516,7 @@ describe('RpcClient test', () => {
   });
 
   describe('getBigMapExpr', () => {
-    it('query the right url and data', async (done) => {
+    it('should query the right url and data', async (done) => {
       await client.getBigMapExpr('1', '2');
 
       expect(httpBackend.createRequest.mock.calls[0][0]).toEqual({
@@ -3457,7 +3528,7 @@ describe('RpcClient test', () => {
   });
 
   describe('getRpcUrl', () => {
-    it('return the RPC Url', () => {
+    it('should return the RPC Url', () => {
       const url = 'https://mainnet.api.tez.ie/';
       const rpcUrlMainnet = new RpcClient(url).getRpcUrl();
       expect(rpcUrlMainnet).toEqual('https://mainnet.api.tez.ie/');
@@ -3467,7 +3538,7 @@ describe('RpcClient test', () => {
   });
 
   describe('getCurrentPeriod', () => {
-    it('query the right url and data', async (done) => {
+    it('should query the right url and data', async (done) => {
       const mockedResponse = {
         voting_period: {
           index: 87,
@@ -3491,7 +3562,7 @@ describe('RpcClient test', () => {
   });
 
   describe('getSuccessorPeriod', () => {
-    it('query the right url and data', async (done) => {
+    it('should query the right url and data', async (done) => {
       const mockedResponse = {
         voting_period: {
           index: 87,
@@ -3515,7 +3586,7 @@ describe('RpcClient test', () => {
   });
 
   describe('getSaplingDiffById', () => {
-    it('query the right url', async (done) => {
+    it('should query the right url', async (done) => {
       httpBackend.createRequest.mockResolvedValue({
         root: 'fbc2f4300c01f0b7820d00e3347c8da4ee614674376cbc45359daa54f9b5493e',
         commitments_and_ciphertexts: [],
@@ -3539,7 +3610,7 @@ describe('RpcClient test', () => {
   });
 
   describe('getSaplingDiffByContract', () => {
-    it('query the right url', async (done) => {
+    it('should query the right url', async (done) => {
       httpBackend.createRequest.mockResolvedValue({
         root: 'fbc2f4300c01f0b7820d00e3347c8da4ee614674376cbc45359daa54f9b5493e',
         commitments_and_ciphertexts: [],
@@ -3565,7 +3636,7 @@ describe('RpcClient test', () => {
   });
 
   describe('getProtocols', () => {
-    it('query the right url and return a ProtocolsResponse', async (done) => {
+    it('should query the right url and return a ProtocolsResponse', async (done) => {
       httpBackend.createRequest.mockReturnValue(
         Promise.resolve({
           protocol: 'PtHangz2aRngywmSRGGvrcTyMbbdpWdpFKuS4uMWxg2RaH9i1qx',
diff --git a/packages/taquito/test/batch/rpc-batch-provider.spec.ts b/packages/taquito/test/batch/rpc-batch-provider.spec.ts
index 0833b72f0..2a26a8664 100644
--- a/packages/taquito/test/batch/rpc-batch-provider.spec.ts
+++ b/packages/taquito/test/batch/rpc-batch-provider.spec.ts
@@ -566,6 +566,134 @@ describe('OperationBatch test', () => {
     });
   });
 
+  describe('withIncreasePaidStorage batch operation', () => {
+    it('should produce an operation batch which contains an increasePaidStorage operation', async (done) => {
+      const estimate = new Estimate(1230000, 93, 142, 250);
+      mockEstimate.batch.mockResolvedValue([estimate]);
+
+      const opToBatch: ParamsWithKind[] = [
+        {
+          kind: OpKind.INCREASE_PAID_STORAGE,
+          amount: 1,
+          destination: 'KT1UiLW7MQCrgaG8pubSJsnpFZzxB2PMs92W',
+        },
+      ];
+
+      const batchOp = await operationBatch.with(opToBatch).send();
+      expect(batchOp.raw).toEqual({
+        counter: 123456,
+        opOb: {
+          branch: 'test',
+          contents: [
+            {
+              kind: 'increase_paid_storage',
+              source: 'test_pub_key_hash',
+              fee: '475',
+              gas_limit: '1330',
+              storage_limit: '93',
+              amount: '1',
+              destination: 'KT1UiLW7MQCrgaG8pubSJsnpFZzxB2PMs92W',
+              counter: '123457',
+            },
+          ],
+          protocol: 'test_proto',
+          signature: 'test_sig',
+        },
+        opbytes: 'test',
+      });
+      done();
+    });
+
+    it('should produce an operation batch which contains a reveal and an increasePaidStorage operation', async (done) => {
+      mockRpcClient.getManagerKey.mockResolvedValue(null);
+      const estimateReveal = new Estimate(1000000, 0, 64, 250);
+      const estimate = new Estimate(1230000, 93, 142, 250);
+      mockEstimate.batch.mockResolvedValue([estimateReveal, estimate]);
+
+      const opToBatch: ParamsWithKind[] = [
+        {
+          kind: OpKind.INCREASE_PAID_STORAGE,
+          amount: 1,
+          destination: 'KT1UiLW7MQCrgaG8pubSJsnpFZzxB2PMs92W',
+        },
+      ];
+
+      const batchOp = await operationBatch.with(opToBatch).send();
+
+      expect(batchOp.raw).toEqual({
+        counter: 123456,
+        opOb: {
+          branch: 'test',
+          contents: [
+            {
+              counter: '123457',
+              fee: '374',
+              gas_limit: '1100',
+              kind: 'reveal',
+              public_key: 'test_pub_key',
+              source: 'test_pub_key_hash',
+              storage_limit: '0',
+            },
+            {
+              kind: 'increase_paid_storage',
+              source: 'test_pub_key_hash',
+              fee: '475',
+              gas_limit: '1330',
+              storage_limit: '93',
+              amount: '1',
+              destination: 'KT1UiLW7MQCrgaG8pubSJsnpFZzxB2PMs92W',
+              counter: '123458',
+            },
+          ],
+          protocol: 'test_proto',
+          signature: 'test_sig',
+        },
+        opbytes: 'test',
+      });
+      done();
+    });
+
+    it('should produce a batch operation which contants an increasePaidStorage operation where fee, gas limit, and storage limit are specified by the user', async (done) => {
+      const estimate = new Estimate(1230000, 93, 142, 250);
+      mockEstimate.batch.mockResolvedValue([estimate]);
+
+      const opToBatch: ParamsWithKind[] = [
+        {
+          kind: OpKind.INCREASE_PAID_STORAGE,
+          fee: 500,
+          gasLimit: 1400,
+          storageLimit: 100,
+          amount: 1,
+          destination: 'KT1UiLW7MQCrgaG8pubSJsnpFZzxB2PMs92W',
+        },
+      ];
+
+      const batchOp = await operationBatch.with(opToBatch).send();
+      expect(batchOp.raw).toEqual({
+        counter: 123456,
+        opOb: {
+          branch: 'test',
+          contents: [
+            {
+              kind: 'increase_paid_storage',
+              source: 'test_pub_key_hash',
+              fee: '500',
+              gas_limit: '1400',
+              storage_limit: '100',
+              amount: '1',
+              destination: 'KT1UiLW7MQCrgaG8pubSJsnpFZzxB2PMs92W',
+              counter: '123457',
+            },
+          ],
+          protocol: 'test_proto',
+          signature: 'test_sig',
+        },
+        opbytes: 'test',
+      });
+      done();
+    });
+  });
+
   describe('with txRollupOriginate operation', () => {
     it('should produce a batch operation which contains an txRollupOriginate operation', async (done) => {
       const estimate = new Estimate(1230000, 93, 142, 250);
@@ -757,7 +885,7 @@ describe('OperationBatch test', () => {
       done();
     });
 
-    it('should produce a batch operation which contains a reveal and a txRollupSubmitBatchp operation', async (done) => {
+    it('should produce a batch operation which contains a reveal and a txRollupSubmitBatch operation', async (done) => {
       mockRpcClient.getManagerKey.mockResolvedValue(null);
       const estimateReveal = new Estimate(1000000, 0, 64, 250);
       const estimate = new Estimate(1230000, 93, 142, 250);
diff --git a/packages/taquito/test/contract/rpc-contract-provider.spec.ts b/packages/taquito/test/contract/rpc-contract-provider.spec.ts
index ace5a59f0..3320788ed 100644
--- a/packages/taquito/test/contract/rpc-contract-provider.spec.ts
+++ b/packages/taquito/test/contract/rpc-contract-provider.spec.ts
@@ -80,7 +80,8 @@ describe('RpcContractProvider test', () => {
     registerGlobalConstant: jest.Mock<any, any>;
     txRollupOriginate: jest.Mock<any, any>;
     txRollupSubmitBatch: jest.Mock<any, any>;
-    transferTicket: jest.Mock<any,any>;
+    transferTicket: jest.Mock<any, any>;
+    increasePaidStorage: jest.Mock<any, any>;
   };
 
   const revealOp = (source: string) => ({
@@ -134,6 +135,7 @@ describe('RpcContractProvider test', () => {
       txRollupOriginate: jest.fn(),
       txRollupSubmitBatch: jest.fn(),
       transferTicket: jest.fn(),
+      increasePaidStorage: jest.fn(),
     };
 
     // Required for operations confirmation polling
@@ -1237,8 +1239,8 @@ describe('RpcContractProvider test', () => {
     });
   });
 
-  describe("transferTicket", () => {
-    it("validate that a reveal operation will be added when needed", async (done) => {
+  describe('transferTicket', () => {
+    it('validate that a reveal operation will be added when needed', async (done) => {
       mockRpcClient.getManagerKey.mockReturnValue(null);
 
       const params: TransferTicketParams = {
@@ -1246,174 +1248,177 @@ describe('RpcContractProvider test', () => {
         fee: 804,
         gasLimit: 5009,
         storageLimit: 130,
-        ticketContents: { "string": "foobar" },
-        ticketTy: { "prim": "string" },
+        ticketContents: { string: 'foobar' },
+        ticketTy: { prim: 'string' },
         ticketTicketer: 'KT1AL8we1Bfajn2M7i3gQM5PJEuyD36sXaYb',
         ticketAmount: 2,
         destination: 'KT1SUT2TBFPCknkBxLqM5eJZKoYVY6mB26Fg',
         entrypoint: 'default',
-        };
-      const result = await rpcContractProvider.transferTicket(params)
-
-      const expectedReveal = revealOp('test_pub_key_hash')
-
-      const expecteReturn = {
-        counter: "2",
-        destination: "KT1SUT2TBFPCknkBxLqM5eJZKoYVY6mB26Fg",
-        entrypoint: "default",
-        fee: "804",
-        gas_limit: "5009",
-        kind: "transfer_ticket",
-        source: "tz1iedjFYksExq8snZK9MNo4AvXHBdXfTsGX",
-        storage_limit: "130",
-        ticket_amount: "2",
+      };
+      const result = await rpcContractProvider.transferTicket(params);
+
+      const expectedReveal = revealOp('test_pub_key_hash');
+
+      const expectedReturn = {
+        counter: '2',
+        destination: 'KT1SUT2TBFPCknkBxLqM5eJZKoYVY6mB26Fg',
+        entrypoint: 'default',
+        fee: '804',
+        gas_limit: '5009',
+        kind: 'transfer_ticket',
+        source: 'tz1iedjFYksExq8snZK9MNo4AvXHBdXfTsGX',
+        storage_limit: '130',
+        ticket_amount: '2',
         ticket_contents: {
-          string: "foobar",
+          string: 'foobar',
         },
-        ticket_ticketer: "KT1AL8we1Bfajn2M7i3gQM5PJEuyD36sXaYb",
+        ticket_ticketer: 'KT1AL8we1Bfajn2M7i3gQM5PJEuyD36sXaYb',
         ticket_ty: {
-          prim: "string",
-        }
-      }
-      const actual = result.raw.opOb.contents ?? []
-      expect(actual[0]).toEqual(expectedReveal)
-      expect(actual[1]).toEqual(expecteReturn)
-      done()
-    })
-    it("validate that a reveal option wont be added when not needed", async (done) => {
+          prim: 'string',
+        },
+      };
+      const actual = result.raw.opOb.contents ?? [];
+      expect(actual[0]).toEqual(expectedReveal);
+      expect(actual[1]).toEqual(expectedReturn);
+      done();
+    });
+
+    it('validate that a reveal option wont be added when not needed', async (done) => {
       mockRpcClient.getManagerKey.mockReturnValue('test_pub_key');
-      mockEstimate.reveal.mockResolvedValue(undefined)
+      mockEstimate.reveal.mockResolvedValue(undefined);
       const params: TransferTicketParams = {
         source: 'tz1iedjFYksExq8snZK9MNo4AvXHBdXfTsGX',
         fee: 804,
         gasLimit: 5009,
         storageLimit: 130,
-        ticketContents: { "string": "foobar" },
-        ticketTy: { "prim": "string" },
+        ticketContents: { string: 'foobar' },
+        ticketTy: { prim: 'string' },
         ticketTicketer: 'KT1AL8we1Bfajn2M7i3gQM5PJEuyD36sXaYb',
         ticketAmount: 2,
         destination: 'KT1SUT2TBFPCknkBxLqM5eJZKoYVY6mB26Fg',
         entrypoint: 'default',
-        };
+      };
       const result = await rpcContractProvider.transferTicket(params);
-      const expecteReturn = {
-        counter: "1",
-        destination: "KT1SUT2TBFPCknkBxLqM5eJZKoYVY6mB26Fg",
-        entrypoint: "default",
-        fee: "804",
-        gas_limit: "5009",
-        kind: "transfer_ticket",
-        source: "tz1iedjFYksExq8snZK9MNo4AvXHBdXfTsGX",
-        storage_limit: "130",
-        ticket_amount: "2",
+      const expectedReturn = {
+        counter: '1',
+        destination: 'KT1SUT2TBFPCknkBxLqM5eJZKoYVY6mB26Fg',
+        entrypoint: 'default',
+        fee: '804',
+        gas_limit: '5009',
+        kind: 'transfer_ticket',
+        source: 'tz1iedjFYksExq8snZK9MNo4AvXHBdXfTsGX',
+        storage_limit: '130',
+        ticket_amount: '2',
         ticket_contents: {
-          string: "foobar",
+          string: 'foobar',
         },
-        ticket_ticketer: "KT1AL8we1Bfajn2M7i3gQM5PJEuyD36sXaYb",
+        ticket_ticketer: 'KT1AL8we1Bfajn2M7i3gQM5PJEuyD36sXaYb',
         ticket_ty: {
-          prim: "string",
-        }
-      }
-      const actual = result.raw.opOb.contents ?? []
+          prim: 'string',
+        },
+      };
+      const actual = result.raw.opOb.contents ?? [];
+
+      expect(actual[0]).toEqual(expectedReturn);
+      done();
+    });
 
-      expect(actual[0]).toEqual(expecteReturn)
-      done()
-    })
-    it("validate that the user-specified fees will be taken into account when specified", async (done) => {
+    it('validate that the user-specified fees will be taken into account when specified', async (done) => {
       const params: TransferTicketParams = {
         source: 'tz1iedjFYksExq8snZK9MNo4AvXHBdXfTsGX',
         fee: 804,
         gasLimit: 5009,
         storageLimit: 130,
-        ticketContents: { "string": "foobar" },
-        ticketTy: { "prim": "string" },
+        ticketContents: { string: 'foobar' },
+        ticketTy: { prim: 'string' },
         ticketTicketer: 'KT1AL8we1Bfajn2M7i3gQM5PJEuyD36sXaYb',
         ticketAmount: 2,
         destination: 'KT1SUT2TBFPCknkBxLqM5eJZKoYVY6mB26Fg',
         entrypoint: 'default',
-        };
-      const result = await rpcContractProvider.transferTicket(params)
+      };
+      const result = await rpcContractProvider.transferTicket(params);
       const expectedReveal = {
         counter: 0,
         opOb: {
-          branch: "test",
-          contents:  [
+          branch: 'test',
+          contents: [
             revealOp('test_pub_key_hash'),
             {
-              counter: "2",
-              destination: "KT1SUT2TBFPCknkBxLqM5eJZKoYVY6mB26Fg",
-              entrypoint: "default",
-              fee: "804",
-              gas_limit: "5009",
-              kind: "transfer_ticket",
-              source: "tz1iedjFYksExq8snZK9MNo4AvXHBdXfTsGX",
-              storage_limit: "130",
-              ticket_amount: "2",
+              counter: '2',
+              destination: 'KT1SUT2TBFPCknkBxLqM5eJZKoYVY6mB26Fg',
+              entrypoint: 'default',
+              fee: '804',
+              gas_limit: '5009',
+              kind: 'transfer_ticket',
+              source: 'tz1iedjFYksExq8snZK9MNo4AvXHBdXfTsGX',
+              storage_limit: '130',
+              ticket_amount: '2',
               ticket_contents: {
-                string: "foobar",
+                string: 'foobar',
               },
-              ticket_ticketer: "KT1AL8we1Bfajn2M7i3gQM5PJEuyD36sXaYb",
+              ticket_ticketer: 'KT1AL8we1Bfajn2M7i3gQM5PJEuyD36sXaYb',
               ticket_ty: {
-                prim: "string",
+                prim: 'string',
               },
             },
           ],
-          protocol: "test_proto",
-          signature: "test_sig",
+          protocol: 'test_proto',
+          signature: 'test_sig',
         },
-        opbytes: "test",
-      }
-      expect(result.raw).toEqual(expectedReveal)
-      done()
-    })
-    it("validate that the fees taken from the estimate will be taken when there is no user-specified fees", async (done) => {
+        opbytes: 'test',
+      };
+      expect(result.raw).toEqual(expectedReveal);
+      done();
+    });
+
+    it('validate that the fees taken from the estimate will be taken when there is no user-specified fees', async (done) => {
       const estimate = new Estimate(10000, 1000, 180, 1000);
       mockEstimate.transferTicket.mockResolvedValue(estimate);
 
       const params: TransferTicketParams = {
         source: 'tz1iedjFYksExq8snZK9MNo4AvXHBdXfTsGX',
-        ticketContents: { "string": "foobar" },
-        ticketTy: { "prim": "string" },
+        ticketContents: { string: 'foobar' },
+        ticketTy: { prim: 'string' },
         ticketTicketer: 'KT1AL8we1Bfajn2M7i3gQM5PJEuyD36sXaYb',
         ticketAmount: 2,
         destination: 'KT1SUT2TBFPCknkBxLqM5eJZKoYVY6mB26Fg',
         entrypoint: 'default',
-        };
-      const result = await rpcContractProvider.transferTicket(params)
+      };
+      const result = await rpcContractProvider.transferTicket(params);
       const expected = {
         counter: 0,
         opOb: {
-          branch: "test",
-          contents:  [
+          branch: 'test',
+          contents: [
             revealOp('test_pub_key_hash'),
             {
-              counter: "2",
-              destination: "KT1SUT2TBFPCknkBxLqM5eJZKoYVY6mB26Fg",
-              entrypoint: "default",
+              counter: '2',
+              destination: 'KT1SUT2TBFPCknkBxLqM5eJZKoYVY6mB26Fg',
+              entrypoint: 'default',
               fee: estimate.suggestedFeeMutez.toString(),
               gas_limit: estimate.gasLimit.toString(),
-              kind: "transfer_ticket",
-              source: "tz1iedjFYksExq8snZK9MNo4AvXHBdXfTsGX",
+              kind: 'transfer_ticket',
+              source: 'tz1iedjFYksExq8snZK9MNo4AvXHBdXfTsGX',
               storage_limit: estimate.storageLimit.toString(),
-              ticket_amount: "2",
+              ticket_amount: '2',
               ticket_contents: {
-                string: "foobar",
+                string: 'foobar',
               },
-              ticket_ticketer: "KT1AL8we1Bfajn2M7i3gQM5PJEuyD36sXaYb",
+              ticket_ticketer: 'KT1AL8we1Bfajn2M7i3gQM5PJEuyD36sXaYb',
               ticket_ty: {
-                prim: "string",
+                prim: 'string',
               },
             },
           ],
-          protocol: "test_proto",
-          signature: "test_sig",
+          protocol: 'test_proto',
+          signature: 'test_sig',
         },
-        opbytes: "test",
-      }
-      expect(result.raw).toEqual(expected)
-      done()
-    })
-  })
+        opbytes: 'test',
+      };
+      expect(result.raw).toEqual(expected);
+      done();
+    });
+  });
 
   describe('setDelegate', () => {
     it('should produce a reveal and delegation operation', async (done) => {
@@ -1558,6 +1563,106 @@ describe('RpcContractProvider test', () => {
     });
   });
 
+  describe('increasePaidStorage', () => {
+    it('should produce an increasePaidStorage operation', async (done) => {
+      mockRpcClient.getManagerKey.mockReturnValue('test_pub_key_hash');
+      mockEstimate.reveal.mockResolvedValue(undefined);
+      const estimate = new Estimate(1230000, 93, 142, 250);
+      mockEstimate.increasePaidStorage.mockResolvedValue(estimate);
+      const result = await rpcContractProvider.increasePaidStorage({
+        amount: 1,
+        destination: 'KT1UiLW7MQCrgaG8pubSJsnpFZzxB2PMs92W',
+      });
+      expect(result.raw).toEqual({
+        opbytes: 'test',
+        opOb: {
+          branch: 'test',
+          contents: [
+            {
+              kind: 'increase_paid_storage',
+              source: 'test_pub_key_hash',
+              fee: '475',
+              gas_limit: '1330',
+              storage_limit: '93',
+              amount: '1',
+              destination: 'KT1UiLW7MQCrgaG8pubSJsnpFZzxB2PMs92W',
+              counter: '1',
+            },
+          ],
+          protocol: 'test_proto',
+          signature: 'test_sig',
+        },
+        counter: 0,
+      });
+      done();
+    });
+
+    it('should produce a reveal and an increasePaidStorage operation', async (done) => {
+      const estimate = new Estimate(1230000, 93, 142, 250);
+      mockEstimate.increasePaidStorage.mockResolvedValue(estimate);
+      const result = await rpcContractProvider.increasePaidStorage({
+        amount: 1,
+        destination: 'KT1UiLW7MQCrgaG8pubSJsnpFZzxB2PMs92W',
+      });
+      expect(result.raw).toEqual({
+        opbytes: 'test',
+        opOb: {
+          branch: 'test',
+          contents: [
+            revealOp('test_pub_key_hash'),
+            {
+              kind: 'increase_paid_storage',
+              source: 'test_pub_key_hash',
+              fee: '475',
+              gas_limit: '1330',
+              storage_limit: '93',
+              amount: '1',
+              destination: 'KT1UiLW7MQCrgaG8pubSJsnpFZzxB2PMs92W',
+              counter: '2',
+            },
+          ],
+          protocol: 'test_proto',
+          signature: 'test_sig',
+        },
+        counter: 0,
+      });
+      done();
+    });
+
+    it('should produce a reveal and increasePaidStorageOperation with fees specified', async (done) => {
+      const estimate = new Estimate(1230000, 93, 142, 250);
+      mockEstimate.increasePaidStorage.mockResolvedValue(estimate);
+      const result = await rpcContractProvider.increasePaidStorage({
+        amount: 1,
+        destination: 'KT1UiLW7MQCrgaG8pubSJsnpFZzxB2PMs92W',
+        fee: 500,
+      });
+      expect(result.raw).toEqual({
+        opbytes: 'test',
+        opOb: {
+          branch: 'test',
+          contents: [
+            revealOp('test_pub_key_hash'),
+            {
+              kind: 'increase_paid_storage',
+              source: 'test_pub_key_hash',
+              fee: '500',
+              gas_limit: '1330',
+              storage_limit: '93',
+              amount: '1',
+              destination: 'KT1UiLW7MQCrgaG8pubSJsnpFZzxB2PMs92W',
+              counter: '2',
+            },
+          ],
+          protocol: 'test_proto',
+          signature: 'test_sig',
+        },
+        counter: 0,
+      });
+      done();
+    });
+  });
+
   describe('txRollupOriginate', () => {
     it('should produce a reveal and txRollupOriginate operation', async (done) => {
       const result = await rpcContractProvider.txRollupOriginate({
diff --git a/packages/taquito/test/helpers.ts b/packages/taquito/test/helpers.ts
index efdb16e85..46d66c1a2 100644
--- a/packages/taquito/test/helpers.ts
+++ b/packages/taquito/test/helpers.ts
@@ -9,6 +9,7 @@ import {
   OperationContentsAndResultTxRollupOrigination,
   OperationContentsAndResultTxRollupSubmitBatch,
   OperationContentsAndResultTransferTicket,
+  OperationContentsAndResultIncreasePaidStorage,
 } from '@taquito/rpc';
 
 const defaultTransferData = {
@@ -102,6 +103,17 @@ const defaultTransferTicketData = {
   entrypoint: 'default',
 };
 
+const defaultIncreasePaidStorageData = {
+  kind: OpKind.INCREASE_PAID_STORAGE as OpKind.INCREASE_PAID_STORAGE,
+  source: 'tz2RVendfy3AQGEBwrhXF4kwyRiJUpa7qLnG',
+  fee: '349',
+  counter: '108123',
+  gas_limit: '1000',
+  storage_limit: '0',
+  amount: '2',
+  destination: 'KT1Vjr5PFC2Qm5XbSQZ8MdFZLgYMzwG5WZNh',
+};
+
 const defaultResult = {
   status: 'applied' as OperationResultStatusEnum,
   consumed_milligas: '15952999',
@@ -251,6 +263,35 @@ export class RegisterGlobalConstantOperationBuilder {
   }
 }
 
+export class IncreasePaidStorageOperationBuilder {
+  private result: OperationContentsAndResultIncreasePaidStorage['metadata']['operation_result'] =
+    defaultResult;
+  private data: Omit<OperationContentsAndResultIncreasePaidStorage, 'metadata'>;
+
+  constructor(
+    private _data: Partial<Omit<OperationContentsAndResultIncreasePaidStorage, 'metadata'>> = {}
+  ) {
+    this.data = { ...defaultIncreasePaidStorageData, ...this._data };
+  }
+
+  withResult(
+    result: Partial<OperationContentsAndResultIncreasePaidStorage['metadata']['operation_result']>
+  ) {
+    this.result = { ...defaultResult, ...result };
+    return this;
+  }
+
+  build(): OperationContentsAndResultIncreasePaidStorage {
+    return {
+      ...this.data,
+      metadata: {
+        balance_updates: [],
+        operation_result: this.result,
+      },
+    };
+  }
+}
+
 export class TxRollupOriginationOperationBuilder {
   private result: OperationContentsAndResultTxRollupOrigination['metadata']['operation_result'] =
     defaultResult;
diff --git a/packages/taquito/test/operations/increase-paid-storage-operation.spec.ts b/packages/taquito/test/operations/increase-paid-storage-operation.spec.ts
new file mode 100644
index 000000000..0d349099e
--- /dev/null
+++ b/packages/taquito/test/operations/increase-paid-storage-operation.spec.ts
@@ -0,0 +1,202 @@
+import { ForgedBytes } from '../../src/operations/types';
+import { OperationContentsAndResult } from '@taquito/rpc';
+import { IncreasePaidStorageOperation } from '../../src/operations/increase-paid-storage-operation';
+import { defaultConfigConfirmation } from '../../src/context';
+import { IncreasePaidStorageOperationBuilder } from '../helpers';
+
+describe('IncreasePaidStorage operation', () => {
+  let fakeContext: any;
+  const fakeForgedBytes = {} as ForgedBytes;
+
+  const successfulResult = [
+    {
+      kind: 'increase_paid_storage',
+      source: 'tz2RVendfy3AQGEBwrhXF4kwyRiJUpa7qLnG',
+      fee: '349',
+      counter: '108123',
+      gas_limit: '1000',
+      storage_limit: '0',
+      amount: '2',
+      destination: 'KT1Vjr5PFC2Qm5XbSQZ8MdFZLgYMzwG5WZNh',
+      metadata: {
+        balance_updates: [
+          {
+            kind: 'contract',
+            contract: 'tz2RVendfy3AQGEBwrhXF4kwyRiJUpa7qLnG',
+            change: '-349',
+            origin: 'block',
+          },
+          {
+            kind: 'accumulator',
+            category: 'block fees',
+            change: '349',
+            origin: 'block',
+          },
+        ],
+        operation_result: {
+          status: 'applied',
+          balance_updates: [
+            {
+              kind: 'contract',
+              contract: 'tz2RVendfy3AQGEBwrhXF4kwyRiJUpa7qLnG',
+              change: '-500',
+              origin: 'block',
+            },
+            {
+              kind: 'burned',
+              category: 'storage fees',
+              change: '500',
+              origin: 'block',
+            },
+          ],
+          consumed_milligas: '1000000',
+        },
+      },
+    },
+  ] as OperationContentsAndResult[];
+
+  beforeEach(() => {
+    fakeContext = {
+      rpc: {
+        getBlock: jest.fn(),
+      },
+      config: { ...defaultConfigConfirmation },
+    };
+
+    fakeContext.rpc.getBlock.mockResolvedValue({
+      operations: [[{ hash: 'ooBghN2ok5EpgEuMqYWqvfwNLBiK9eNFoPai91iwqk2nRCyUKgE' }], [], [], []],
+      header: {
+        level: 1,
+      },
+    });
+  });
+
+  it('should return status of IncreasePaidStorage operation', () => {
+    const op = new IncreasePaidStorageOperation(
+      'ooBghN2ok5EpgEuMqYWqvfwNLBiK9eNFoPai91iwqk2nRCyUKgE',
+      {} as any,
+      '',
+      fakeForgedBytes,
+      successfulResult,
+      fakeContext
+    );
+
+    expect(op.status).toEqual('applied');
+  });
+
+  it('should return the consumedMilligas', () => {
+    const op = new IncreasePaidStorageOperation(
+      'ooBghN2ok5EpgEuMqYWqvfwNLBiK9eNFoPai91iwqk2nRCyUKgE',
+      {} as any,
+      '',
+      fakeForgedBytes,
+      successfulResult,
+      fakeContext
+    );
+
+    expect(op.consumedMilliGas).toEqual('1000000');
+  });
+
+  it('should return the fee', () => {
+    const op = new IncreasePaidStorageOperation(
+      'ooBghN2ok5EpgEuMqYWqvfwNLBiK9eNFoPai91iwqk2nRCyUKgE',
+      { fee: 400 } as any,
+      '',
+      fakeForgedBytes,
+      successfulResult,
+      fakeContext
+    );
+
+    expect(op.fee).toEqual(400);
+  });
+
+  it('should return the error if there is one', () => {
+    const tx = new IncreasePaidStorageOperationBuilder();
+    const op = new IncreasePaidStorageOperation(
+      'ooBghN2ok5EpgEuMqYWqvfwNLBiK9eNFoPai91iwqk2nRCyUKgE',
+      {} as any,
+      '',
+      fakeForgedBytes,
+      [
+        tx
+          .withResult({
+            status: 'backtracked',
+            errors: [{ kind: 'temporary', id: 'proto.014-PtKathma.tez.subtraction_underflow' }],
+          })
+          .build(),
+      ],
+      fakeContext
+    );
+
+    expect(op.errors).toBeDefined();
+    expect(op.errors?.[0]).toEqual({
+      kind: 'temporary',
+      id: 'proto.014-PtKathma.tez.subtraction_underflow',
+    });
+  });
+
+  it('should return the gasLimit', () => {
+    const op = new IncreasePaidStorageOperation(
+      'ooBghN2ok5EpgEuMqYWqvfwNLBiK9eNFoPai91iwqk2nRCyUKgE',
+      { gas_limit: 450 } as any,
+      '',
+      fakeForgedBytes,
+      successfulResult,
+      fakeContext
+    );
+
+    expect(op.gasLimit).toEqual(450);
+  });
+
+  it('should return the storageLimit', () => {
+    const op = new IncreasePaidStorageOperation(
+      'ooBghN2ok5EpgEuMqYWqvfwNLBiK9eNFoPai91iwqk2nRCyUKgE',
+      { storage_limit: 450 } as any,
+      '',
+      fakeForgedBytes,
+      successfulResult,
+      fakeContext
+    );
+
+    expect(op.storageLimit).toEqual(450);
+  });
+
+  it('error property should be undefined when no error occurs', () => {
+    const op = new IncreasePaidStorageOperation(
+      'ooBghN2ok5EpgEuMqYWqvfwNLBiK9eNFoPai91iwqk2nRCyUKgE',
+      {} as any,
+      '',
+      fakeForgedBytes,
+      successfulResult,
+      fakeContext
+    );
+
+    expect(op.errors).toBeUndefined();
+  });
+
+  it('should return amount of increased bytes', () => {
+    const op = new IncreasePaidStorageOperation(
+      'ooBghN2ok5EpgEuMqYWqvfwNLBiK9eNFoPai91iwqk2nRCyUKgE',
+      { amount: 1 } as any,
+      '',
+      fakeForgedBytes,
+      successfulResult,
+      fakeContext
+    );
+
+    expect(op.amount).toEqual(1);
+  });
+
+  it('should return destination', () => {
+    const op = new IncreasePaidStorageOperation(
+      'ooBghN2ok5EpgEuMqYWqvfwNLBiK9eNFoPai91iwqk2nRCyUKgE',
+      { destination: 'testDestination' } as any,
+      '',
+      fakeForgedBytes,
+      successfulResult,
+      fakeContext
+    );
+
+    expect(op.destination).toEqual('testDestination');
+  });
+});