diff --git a/idea.md b/idea.md
new file mode 100644
index 00000000..7921fc07
--- /dev/null
+++ b/idea.md
@@ -0,0 +1,164 @@
+# Payment Splitting
+
+## How to calculate the withdrawable amount.
+
+The following is explanation the concept of calculating the amount of tokens a user can withdraw (=`payment`) using pseudocode in JS syntax.
+
+ref: https://github.com/OpenZeppelin/openzeppelin-contracts/blob/v4.9.6/contracts/finance/PaymentSplitter.sol
+
+```javascript!
+const total_released_tokens = new Map([['TOKEN', 0]]);
+const released_tokens_of_user = new Map([['TOKEN', new Map([['USER', 0]])]]);
+
+function withdraw(token, user) {
+ const Property = ERC20(property);
+ const Token = ERC20(token);
+ const total_received =
+ Token.balanceOf(address(this)) +
+ total_released_tokens.get(token);
+
+ /*
+ */
+ const released = released_tokens_of_user.get(token).get(user);
+
+ const user_balance = Property.balanceOf(user);
+ const total_supply = Property.totalSupply();
+ const payment =
+ (total_received * user_balance) / total_supply - released;
+
+ /*
+ * (TRANSFER TOKENS TO THE USER HERE...)
+ */
+ ERC20.safeTransfer(token, user, payment);
+
+ /*
+ * Update the global states.
+ */
+ released_tokens_of_user.get(token).set(user, released + payment)
+ total_released_tokens.set(
+ token,
+ total_released_tokens.get(token) + payment
+ );
+
+ return payment;
+}
+```
+
+## Cases
+
+The withdrawable amount is calculated from the latest share of Property.
+
+### Case-1
+|_timeline_|_event_|Alice|Bob|Locked Value|
+|---|---|---|---|---|
+|1||50%|50%|0|
+|2|+©100|50%|50%|100|
+|3|Alice 20% → Bob|30%|70%|100|
+|4|Alice withdraws
Alice earns ©30|30%|70%|70|
+|5|Bob withdraws
Bob earns ©70|30%|70%|0|
+
+### Case-2
+|_timeline_|_event_|Alice|Bob|Locked Value|
+|---|---|---|---|---|
+|1||50%|50%|0|
+|2|+©100|50%|50%|100|
+|3|Alice withdraws
Alice earns ©50|50%|50%|50|
+|4|Alice 20% → Bob|30%|70%|50|
+|5|+©200|30%|70%|250|
+|6|Bob withdraws
Bob earns ©210|30%|70%|40|
+|7|Alice withdraws
Alice earns ©40|30%|70%|0|
+
+---
+
+# Idea
+
+ref: https://github.com/dev-protocol/protocol-v2/pull/714
+
+### Vault side
+
+Add a call for updating `released` and a local state that records the user balance at the time of the last withdraw.
+
+```diff
+const total_released_tokens = new Map([['TOKEN', 0]]);
+const released_tokens_of_user = new Map([['TOKEN', new Map([['USER', 0]])]]);
++ const last_balance_of_user_for_tokens = new Map([['TOKEN', new Map([['USER', 0]])]]);
+
+function withdraw(token, user) {
+ const Property = ERC20(property);
+ const Token = ERC20(token);
+ const total_received =
+ Token.balanceOf(address(this)) +
+ total_released_tokens.get(token);
+
++ updateReleasedTokens(token, user, Property.balanceOf(user));
+
+ /*
+ */
+ const released = released_tokens_of_user.get(token).get(user);
+
+ const user_balance = Property.balanceOf(user);
+ const total_supply = Property.totalSupply();
+ const payment =
+ (total_received * user_balance) / total_supply - released;
+
+ /*
+ * (TRANSFER TOKENS TO THE USER HERE...)
+ */
+ ERC20.safeTransfer(token, user, payment);
+
+ /*
+ * Update the global states.
+ */
+ released_tokens_of_user.get(token).set(user, released + payment)
+ total_released_tokens.set(
+ token,
+ total_released_tokens.get(token) + payment
+ );
+
++ last_balance_of_user_for_tokens[token][user] = user_balance;
+
+ return payment;
+}
+```
+
+`updateReleasedTokens` updates the value of `released` by referencing `Withdraw.transferHistory` recursively until `last_balance_of_user_for_tokens` matches the latest balance.
+
+```javascript!
+const released_tokens_addresses = new Map([['USER', new Set()]]); // mapping(address => EnumerableSet.AddressSet)
+const Withdraw = Withdraw(Registry(registry).registries('Withdraw'));
+
+function updateReleasedTokens(token, user, current_balance) {
+ if (last_balance_of_user_for_tokens[token][user] === current_balance) {
+ // No need to update it.
+ return
+ }
+
+ const historyIndex = Withdraw.transferHistoryLengthOfRecipient(address(Property), user);
+ let done = false;
+ let i = historyIndex;
+ let calculated = 0;
+ while (!done || i >= 0) {
+ const history = Withdraw.transferHistory(
+ Withdraw.transferHistoryOfRecipientByIndex(i)
+ );
+ if (!history.fill) {
+ // This is always done on the history of the last 1 transfer, and other case, history.fill is true.
+ history.amount = current_balance - history.preBalanceOfRecipient;
+ }
+
+ updateReleasedTokens(token, history.from, Property.balanceOf(history.from));
+
+ const released_tokens = released_tokens_of_user.get(token).get(history.from);
+ const part_of_released = released_tokens * history.preBalanceOfSender / history.amount;
+ released_tokens_of_user.get(token).set(
+ user,
+ part_of_released + released_tokens_of_user.get(token).get(user)
+ );
+
+ i = i - 1;
+ calculated = calculated + history.amount;
+ done = last_balance_of_user_for_tokens[token][user] + calculated === current_balance;
+ }
+}
+```
+