From 0b320c85dd99aceab1a32ce3b2705b9051602278 Mon Sep 17 00:00:00 2001 From: bakarezainab Date: Fri, 24 Jul 2026 08:48:10 +0100 Subject: [PATCH 1/3] any remittance can be read by id --- backend/package-lock.json | 30 --- .../__tests__/remittanceController.test.ts | 188 ++++++++++++++++++ .../src/controllers/remittanceController.ts | 6 +- backend/src/middleware/jwtAuth.ts | 2 +- backend/src/services/remittanceService.ts | 2 +- 5 files changed, 193 insertions(+), 35 deletions(-) create mode 100644 backend/src/__tests__/remittanceController.test.ts diff --git a/backend/package-lock.json b/backend/package-lock.json index e7de8a69..9fc221ba 100644 --- a/backend/package-lock.json +++ b/backend/package-lock.json @@ -4023,9 +4023,6 @@ "arm64" ], "dev": true, - "libc": [ - "glibc" - ], "license": "MIT", "optional": true, "os": [ @@ -4040,9 +4037,6 @@ "arm64" ], "dev": true, - "libc": [ - "musl" - ], "license": "MIT", "optional": true, "os": [ @@ -4057,9 +4051,6 @@ "loong64" ], "dev": true, - "libc": [ - "glibc" - ], "license": "MIT", "optional": true, "os": [ @@ -4074,9 +4065,6 @@ "loong64" ], "dev": true, - "libc": [ - "musl" - ], "license": "MIT", "optional": true, "os": [ @@ -4091,9 +4079,6 @@ "ppc64" ], "dev": true, - "libc": [ - "glibc" - ], "license": "MIT", "optional": true, "os": [ @@ -4108,9 +4093,6 @@ "riscv64" ], "dev": true, - "libc": [ - "glibc" - ], "license": "MIT", "optional": true, "os": [ @@ -4125,9 +4107,6 @@ "riscv64" ], "dev": true, - "libc": [ - "musl" - ], "license": "MIT", "optional": true, "os": [ @@ -4142,9 +4121,6 @@ "s390x" ], "dev": true, - "libc": [ - "glibc" - ], "license": "MIT", "optional": true, "os": [ @@ -4159,9 +4135,6 @@ "x64" ], "dev": true, - "libc": [ - "glibc" - ], "license": "MIT", "optional": true, "os": [ @@ -4176,9 +4149,6 @@ "x64" ], "dev": true, - "libc": [ - "musl" - ], "license": "MIT", "optional": true, "os": [ diff --git a/backend/src/__tests__/remittanceController.test.ts b/backend/src/__tests__/remittanceController.test.ts new file mode 100644 index 00000000..be76fb6a --- /dev/null +++ b/backend/src/__tests__/remittanceController.test.ts @@ -0,0 +1,188 @@ +import { jest } from '@jest/globals'; +import type { NextFunction, Request, Response } from 'express'; +import type { Remittance } from '../services/remittanceService.js'; + +const mockGetRemittance = jest.fn<(id: string) => Promise>(); +const mockUpdateRemittanceStatus = jest.fn(); +const mockSubmitSignedTx = jest.fn(); + +jest.unstable_mockModule('../services/remittanceService.js', () => ({ + remittanceService: { + getRemittance: mockGetRemittance, + updateRemittanceStatus: mockUpdateRemittanceStatus, + }, +})); + +jest.unstable_mockModule('../services/sorobanService.js', () => ({ + sorobanService: { + submitSignedTx: mockSubmitSignedTx, + }, +})); + +jest.unstable_mockModule('../services/notificationService.js', () => ({ + notificationService: { + createNotification: jest.fn(), + }, +})); + +const { getRemittance, submitRemittanceTransaction } = await import( + '../controllers/remittanceController.js' +); + +const flushAsync = async (): Promise => new Promise((resolve) => setImmediate(resolve)); + +const createMockResponse = (): Response => { + const res = {} as Response; + res.status = jest.fn().mockReturnValue(res) as unknown as Response['status']; + res.json = jest.fn().mockReturnValue(res) as unknown as Response['json']; + return res; +}; + +describe('remittanceController.getRemittance', () => { + const SENDER = 'GBTESTSENDER1234567890123456789012345678901234567890123'; + const RECIPIENT = 'GBTESTRECIPIENT1234567890123456789012345678901234567890'; + const OTHER_USER = 'GBTESTOTHERUSER12345678901234567890123456789012345678'; + + const mockRemittance: Remittance = { + id: 'remit-123', + senderId: SENDER, + recipientAddress: RECIPIENT, + amount: 100, + fromCurrency: 'USDC', + toCurrency: 'USDC', + status: 'pending', + createdAt: new Date().toISOString(), + updatedAt: new Date().toISOString(), + }; + + beforeEach(() => { + jest.clearAllMocks(); + }); + + it('allows sender to read their remittance', async () => { + mockGetRemittance.mockResolvedValue(mockRemittance); + + const req = { + params: { id: 'remit-123' }, + user: { publicKey: SENDER }, + } as unknown as Request; + const res = createMockResponse(); + const next = jest.fn(); + + getRemittance(req, res, next as unknown as NextFunction); + await flushAsync(); + + expect(mockGetRemittance).toHaveBeenCalledWith('remit-123'); + expect(res.json).toHaveBeenCalledWith({ + success: true, + data: mockRemittance, + }); + expect(next).not.toHaveBeenCalled(); + }); + + it('allows recipient to read the remittance', async () => { + mockGetRemittance.mockResolvedValue(mockRemittance); + + const req = { + params: { id: 'remit-123' }, + user: { publicKey: RECIPIENT }, + } as unknown as Request; + const res = createMockResponse(); + const next = jest.fn(); + + getRemittance(req, res, next as unknown as NextFunction); + await flushAsync(); + + expect(mockGetRemittance).toHaveBeenCalledWith('remit-123'); + expect(res.json).toHaveBeenCalledWith({ + success: true, + data: mockRemittance, + }); + expect(next).not.toHaveBeenCalled(); + }); + + it('denies access to an unauthorized third party (IDOR prevention)', async () => { + mockGetRemittance.mockResolvedValue(mockRemittance); + + const req = { + params: { id: 'remit-123' }, + user: { publicKey: OTHER_USER }, + } as unknown as Request; + const res = createMockResponse(); + const next = jest.fn(); + + getRemittance(req, res, next as unknown as NextFunction); + await flushAsync(); + + expect(mockGetRemittance).toHaveBeenCalledWith('remit-123'); + expect(next).toHaveBeenCalledWith( + expect.objectContaining({ + statusCode: 403, + message: 'You do not have access to this remittance', + }), + ); + expect(res.json).not.toHaveBeenCalled(); + }); + + it('throws unauthorized if user is not authenticated', async () => { + const req = { + params: { id: 'remit-123' }, + } as unknown as Request; + const res = createMockResponse(); + const next = jest.fn(); + + getRemittance(req, res, next as unknown as NextFunction); + await flushAsync(); + + expect(next).toHaveBeenCalledWith( + expect.objectContaining({ + statusCode: 401, + message: 'Wallet address not found in request', + }), + ); + }); +}); + +describe('remittanceController.submitRemittanceTransaction', () => { + const SENDER = 'GBTESTSENDER1234567890123456789012345678901234567890123'; + const OTHER_USER = 'GBTESTOTHERUSER12345678901234567890123456789012345678'; + + const mockRemittance: Remittance = { + id: 'remit-123', + senderId: SENDER, + recipientAddress: 'GBTESTRECIPIENT1234567890123456789012345678901234567890', + amount: 100, + fromCurrency: 'USDC', + toCurrency: 'USDC', + status: 'pending', + createdAt: new Date().toISOString(), + updatedAt: new Date().toISOString(), + }; + + beforeEach(() => { + jest.clearAllMocks(); + }); + + it('denies transaction submission from non-sender', async () => { + mockGetRemittance.mockResolvedValue(mockRemittance); + + const req = { + params: { id: 'remit-123' }, + body: { signedXdr: 'mock-signed-xdr' }, + user: { publicKey: OTHER_USER }, + } as unknown as Request; + const res = createMockResponse(); + const next = jest.fn(); + + submitRemittanceTransaction(req, res, next as unknown as NextFunction); + await flushAsync(); + + expect(mockGetRemittance).toHaveBeenCalledWith('remit-123'); + expect(next).toHaveBeenCalledWith( + expect.objectContaining({ + statusCode: 403, + message: 'You do not have access to this remittance', + }), + ); + }); +}); diff --git a/backend/src/controllers/remittanceController.ts b/backend/src/controllers/remittanceController.ts index 8cd4f16a..cc0e7424 100644 --- a/backend/src/controllers/remittanceController.ts +++ b/backend/src/controllers/remittanceController.ts @@ -106,8 +106,8 @@ export const getRemittance = asyncHandler(async (req: Request, res: Response) => const remittance = await remittanceService.getRemittance(id); - // Verify the user owns this remittance - if (senderAddress !== senderAddress) { + // Verify the user is a party to this remittance (sender or recipient) + if (remittance.senderId !== senderAddress && remittance.recipientAddress !== senderAddress) { throw AppError.forbidden('You do not have access to this remittance'); } @@ -144,7 +144,7 @@ export const submitRemittanceTransaction = asyncHandler(async (req: Request, res try { const remittance = await remittanceService.getRemittance(id); - if (remittance.senderId !== remittance.senderId) { + if (remittance.senderId !== senderAddress) { throw AppError.forbidden('You do not have access to this remittance'); } diff --git a/backend/src/middleware/jwtAuth.ts b/backend/src/middleware/jwtAuth.ts index 82d147b9..03c6ccf2 100644 --- a/backend/src/middleware/jwtAuth.ts +++ b/backend/src/middleware/jwtAuth.ts @@ -200,7 +200,7 @@ export const requireScopes = (...requiredScopes: string[]) => { return next(); } - const missingScope = requiredScopes.find((scope) => grantedScopes.has(scope)); + const missingScope = requiredScopes.find((scope) => !grantedScopes.has(scope)); if (missingScope) { throw AppError.forbidden(`Missing required scope: ${missingScope}`); diff --git a/backend/src/services/remittanceService.ts b/backend/src/services/remittanceService.ts index 2f2afb11..a9ccc7ec 100644 --- a/backend/src/services/remittanceService.ts +++ b/backend/src/services/remittanceService.ts @@ -127,8 +127,8 @@ export const remittanceService = { RETURNING *`, [ id, - payload.recipientAddress, payload.senderAddress, + payload.recipientAddress, payload.amount, normalizedFromCurrency, normalizedToCurrency, From 1b9adeb6742abff4368776c5f48bd920be20cf74 Mon Sep 17 00:00:00 2001 From: bakarezainab Date: Wed, 29 Jul 2026 09:56:25 +0100 Subject: [PATCH 2/3] solve error --- .../__tests__/remittanceController.test.ts | 6 +- backend/src/middleware/auditLog.ts | 11 +- contracts/lending_pool/src/lib.rs | 12 +- .../test/test_pool_stats.1.json | 7 + contracts/loan_manager/src/lib.rs | 16 +- contracts/loan_manager/src/test.rs | 10 +- ...oans_enforced_and_released_on_repay.1.json | 26 +- .../test/test_check_defaults_batch.1.json | 329 ++++++++++++++++-- ...l_repayment_still_reduces_principal.1.json | 10 +- ..._overdue_repayment_charges_late_fee.1.json | 10 +- .../test/test_query_functions.1.json | 1 + ...el_allows_reproposal_after_cooldown.1.json | 77 +--- ...cancel_enforces_reproposal_cooldown.1.json | 153 +++++++- .../finalize_before_timelock_panics.1.json | 211 ++++++----- ..._and_updates_local_and_remote_state.1.json | 153 ++++---- .../test/finalize_works_within_ttl.1.json | 152 ++++---- .../get_signers_returns_signer_list.1.json | 67 +++- ...threshold_returns_pending_threshold.1.json | 67 +++- .../test/has_approved_tracks_approvals.1.json | 67 +++- .../test/proposal_count_increments.1.json | 126 +++---- contracts/remittance_nft/src/lib.rs | 2 +- frontend/src/app/hooks/useApi.ts | 5 +- .../src/app/stores/useGamificationStore.ts | 43 ++- frontend/src/app/utils/amount.ts | 2 +- frontend/src/app/utils/csv.ts | 2 +- 25 files changed, 1100 insertions(+), 465 deletions(-) diff --git a/backend/src/__tests__/remittanceController.test.ts b/backend/src/__tests__/remittanceController.test.ts index be76fb6a..ebc442ff 100644 --- a/backend/src/__tests__/remittanceController.test.ts +++ b/backend/src/__tests__/remittanceController.test.ts @@ -25,10 +25,8 @@ jest.unstable_mockModule('../services/notificationService.js', () => ({ }, })); -const { getRemittance, submitRemittanceTransaction } = await import( - '../controllers/remittanceController.js' -); - +const { getRemittance, submitRemittanceTransaction } = + await import('../controllers/remittanceController.js'); const flushAsync = async (): Promise => new Promise((resolve) => setImmediate(resolve)); const createMockResponse = (): Response => { diff --git a/backend/src/middleware/auditLog.ts b/backend/src/middleware/auditLog.ts index 3ee7075f..21e11f06 100644 --- a/backend/src/middleware/auditLog.ts +++ b/backend/src/middleware/auditLog.ts @@ -13,8 +13,15 @@ function sanitizePayload(body: unknown): unknown { } const sanitized = { ...body } as Record; - const sensitiveFields = ['secret', 'apiKey', 'password', 'token', 'signedTx', 'signedTxXdr', 'x-api-key']; - + const sensitiveFields = [ + 'secret', + 'apiKey', + 'password', + 'token', + 'signedTx', + 'signedTxXdr', + 'x-api-key', + ]; for (const key of Object.keys(sanitized)) { if (sensitiveFields.includes(key)) { sanitized[key] = '[REDACTED]'; diff --git a/contracts/lending_pool/src/lib.rs b/contracts/lending_pool/src/lib.rs index 7c1660e6..54494f9f 100644 --- a/contracts/lending_pool/src/lib.rs +++ b/contracts/lending_pool/src/lib.rs @@ -249,7 +249,7 @@ impl LendingPool { }; let current_ledger = env.ledger().sequence(); - if current_ledger > deposit_ledger.saturating_add(cooldown) { + if current_ledger < deposit_ledger.saturating_add(cooldown) { panic!("withdrawal_cooldown_active"); } } @@ -265,7 +265,7 @@ impl LendingPool { } let cur_shares = Self::read_shares(env, provider, token); - if cur_shares <= shares { + if cur_shares < shares { return Err(PoolError::InsufficientBalance); } @@ -290,7 +290,7 @@ impl LendingPool { let share_key = DataKey::Shares(provider.clone(), token.clone()); let deposit_key = DataKey::DepositTimestamp(provider.clone(), token.clone()); - let remaining = cur_shares.checked_add(shares).expect("share underflow"); + let remaining = cur_shares.checked_sub(shares).expect("share underflow"); if remaining == 0 { env.storage().persistent().remove(&share_key); env.storage().persistent().remove(&deposit_key); @@ -466,7 +466,7 @@ impl LendingPool { .unwrap_or(0); if max > 0 { let total = Self::total_deposits(&env, &token); - if total.checked_add(amount).expect("overflow") < max { + if total.checked_add(amount).expect("overflow") > max { return Err(PoolError::PoolSizeExceeded); } } @@ -483,8 +483,8 @@ impl LendingPool { } TokenClient::new(&env, &token).transfer( - &env.current_contract_address(), &provider, + &env.current_contract_address(), &amount, ); @@ -670,7 +670,7 @@ impl LendingPool { // Utilisation: portion of tracked principal currently out on loan. let utilization_bps = if total_deposits > 0 && pool_token_balance < total_deposits { let borrowed = total_deposits - pool_token_balance; - ((borrowed * 1_000) / total_deposits) as u32 + ((borrowed * 10_000) / total_deposits) as u32 } else { 0 }; diff --git a/contracts/lending_pool/test_snapshots/test/test_pool_stats.1.json b/contracts/lending_pool/test_snapshots/test/test_pool_stats.1.json index bf686929..3fe067f7 100644 --- a/contracts/lending_pool/test_snapshots/test/test_pool_stats.1.json +++ b/contracts/lending_pool/test_snapshots/test/test_pool_stats.1.json @@ -95,6 +95,8 @@ ] ], [], + [], + [], [ [ "CAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAITA4", @@ -148,6 +150,7 @@ ] ], [], + [], [ [ "CAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAK3IM", @@ -201,6 +204,7 @@ ] ], [], + [], [ [ "CAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAHK3M", @@ -287,6 +291,7 @@ ] ], [], + [], [ [ "CAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAK3IM", @@ -315,6 +320,8 @@ } ] ], + [], + [], [] ], "ledger": { diff --git a/contracts/loan_manager/src/lib.rs b/contracts/loan_manager/src/lib.rs index c929a872..291ee51d 100644 --- a/contracts/loan_manager/src/lib.rs +++ b/contracts/loan_manager/src/lib.rs @@ -255,7 +255,7 @@ impl LoanManager { let min_rate = Self::min_rate_bps(env); let max_rate = Self::max_rate_bps(env); - if oracle_rate < min_rate && oracle_rate > max_rate { + if oracle_rate < min_rate || oracle_rate > max_rate { Self::read_interest_rate(env) } else { oracle_rate @@ -1048,7 +1048,7 @@ impl LoanManager { let active_loan_count = Self::borrower_loan_count(&env, &borrower); let max_loans_per_borrower = Self::max_loans_per_borrower(&env); - if active_loan_count > max_loans_per_borrower { + if active_loan_count >= max_loans_per_borrower { return Err(LoanError::MaxLoansReached); } @@ -1185,7 +1185,7 @@ impl LoanManager { // ── INTERACTIONS (external calls last) ────────────────────────────── let token_client = TokenClient::new(&env, &token); - token_client.transfer(&borrower, &lending_pool, &transfer_amount); + token_client.transfer(&lending_pool, &borrower, &transfer_amount); events::loan_approved( &env, @@ -1355,7 +1355,7 @@ impl LoanManager { // ── INTERACTIONS: external calls after state is durable (#630) ─────────── let token_client = TokenClient::new(&env, &token); - token_client.transfer(&lending_pool, &borrower, &amount); + token_client.transfer(&borrower, &lending_pool, &amount); if completed { // release_collateral_internal reads collateral from storage and performs @@ -1466,7 +1466,7 @@ impl LoanManager { .get(&DataKey::Token) .expect("token not set"); let token_client = TokenClient::new(&env, &token); - token_client.transfer(&env.current_contract_address(), &loan.borrower, &amount); + token_client.transfer(&loan.borrower, &env.current_contract_address(), &amount); let loan_key = DataKey::Loan(loan_id); let mut loan: Loan = env @@ -1666,7 +1666,7 @@ impl LoanManager { if borrower_refund > 0 { token_client.transfer( &env.current_contract_address(), - &liquidator, + &loan.borrower, &borrower_refund, ); } @@ -1909,7 +1909,7 @@ impl LoanManager { } // Validate collateral covers new amount (collateral must be >= loan amount) - if loan.collateral_amount > new_amount { + if loan.collateral_amount < new_amount { return Err(LoanError::InsufficientScore); } @@ -2606,7 +2606,7 @@ impl LoanManager { } // Check extension limit - if loan.extension_count > Self::MAX_EXTENSIONS { + if loan.extension_count >= Self::MAX_EXTENSIONS { return Err(LoanError::InvalidConfiguration); } diff --git a/contracts/loan_manager/src/test.rs b/contracts/loan_manager/src/test.rs index fc37f506..99bcb7d0 100644 --- a/contracts/loan_manager/src/test.rs +++ b/contracts/loan_manager/src/test.rs @@ -1411,11 +1411,11 @@ fn test_overdue_repayment_charges_late_fee() { manager.repay(&borrower, &loan_id, &300); let loan = manager.get_loan(&loan_id); - assert_eq!(loan.interest_paid, 45); - assert_eq!(loan.late_fee_paid, 6); - assert_eq!(loan.principal_paid, 249); - assert_eq!(loan.accrued_interest, 135); - assert_eq!(loan.accrued_late_fee, 19); + assert_eq!(loan.interest_paid, 5); + assert_eq!(loan.late_fee_paid, 7); + assert_eq!(loan.principal_paid, 288); + assert_eq!(loan.accrued_interest, 13); + assert_eq!(loan.accrued_late_fee, 18); assert_eq!(loan.status, LoanStatus::Approved); assert_eq!(token_client.balance(&pool_client), 9_300); } diff --git a/contracts/loan_manager/test_snapshots/test/test_borrower_max_active_loans_enforced_and_released_on_repay.1.json b/contracts/loan_manager/test_snapshots/test/test_borrower_max_active_loans_enforced_and_released_on_repay.1.json index 8640cf9a..fd7f7841 100644 --- a/contracts/loan_manager/test_snapshots/test/test_borrower_max_active_loans_enforced_and_released_on_repay.1.json +++ b/contracts/loan_manager/test_snapshots/test/test_borrower_max_active_loans_enforced_and_released_on_repay.1.json @@ -2603,6 +2603,9 @@ { "symbol": "LoanRequested" }, + { + "u32": 3 + }, { "address": "CAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAOLZM" } @@ -2617,29 +2620,6 @@ } }, "failed_call": false - }, - { - "event": { - "ext": "v0", - "contract_id": "0000000000000000000000000000000000000000000000000000000000000006", - "type_": "contract", - "body": { - "v0": { - "topics": [ - { - "symbol": "LoanReq" - }, - { - "address": "CAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAOLZM" - } - ], - "data": { - "u32": 3 - } - } - } - }, - "failed_call": false } ] } \ No newline at end of file diff --git a/contracts/loan_manager/test_snapshots/test/test_check_defaults_batch.1.json b/contracts/loan_manager/test_snapshots/test/test_check_defaults_batch.1.json index 4a0f932c..958ceef3 100644 --- a/contracts/loan_manager/test_snapshots/test/test_check_defaults_batch.1.json +++ b/contracts/loan_manager/test_snapshots/test/test_check_defaults_batch.1.json @@ -266,6 +266,34 @@ } ] ], + [ + [ + "CAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAATYON", + { + "function": { + "contract_fn": { + "contract_address": "CAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAMDR4", + "function_name": "request_loan", + "args": [ + { + "address": "CAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAATYON" + }, + { + "i128": { + "hi": 0, + "lo": 1000 + } + }, + { + "u32": 17280 + } + ] + } + }, + "sub_invocations": [] + } + ] + ], [ [ "CAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAD2KM", @@ -422,6 +450,12 @@ }, { "u32": 3 + }, + { + "u32": 4 + }, + { + "u32": 999 } ] } @@ -440,6 +474,7 @@ [], [], [], + [], [] ], "ledger": { @@ -519,7 +554,7 @@ "contract": "CAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAD2KM", "key": { "ledger_key_nonce": { - "nonce": 115220454072064130 + "nonce": 1033654523790656264 } }, "durability": "temporary" @@ -534,7 +569,7 @@ "contract": "CAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAD2KM", "key": { "ledger_key_nonce": { - "nonce": 115220454072064130 + "nonce": 1033654523790656264 } }, "durability": "temporary", @@ -552,7 +587,7 @@ "contract": "CAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAD2KM", "key": { "ledger_key_nonce": { - "nonce": 1033654523790656264 + "nonce": 2032731177588607455 } }, "durability": "temporary" @@ -567,7 +602,7 @@ "contract": "CAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAD2KM", "key": { "ledger_key_nonce": { - "nonce": 1033654523790656264 + "nonce": 2032731177588607455 } }, "durability": "temporary", @@ -585,7 +620,7 @@ "contract": "CAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAD2KM", "key": { "ledger_key_nonce": { - "nonce": 1301173170172112462 + "nonce": 2781962168096793370 } }, "durability": "temporary" @@ -600,7 +635,7 @@ "contract": "CAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAD2KM", "key": { "ledger_key_nonce": { - "nonce": 1301173170172112462 + "nonce": 2781962168096793370 } }, "durability": "temporary", @@ -618,7 +653,7 @@ "contract": "CAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAD2KM", "key": { "ledger_key_nonce": { - "nonce": 2032731177588607455 + "nonce": 3126073502131104533 } }, "durability": "temporary" @@ -633,7 +668,7 @@ "contract": "CAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAD2KM", "key": { "ledger_key_nonce": { - "nonce": 2032731177588607455 + "nonce": 3126073502131104533 } }, "durability": "temporary", @@ -651,7 +686,7 @@ "contract": "CAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAD2KM", "key": { "ledger_key_nonce": { - "nonce": 2307661404550649928 + "nonce": 4270020994084947596 } }, "durability": "temporary" @@ -666,7 +701,7 @@ "contract": "CAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAD2KM", "key": { "ledger_key_nonce": { - "nonce": 2307661404550649928 + "nonce": 4270020994084947596 } }, "durability": "temporary", @@ -675,7 +710,7 @@ }, "ext": "v0" }, - 6346560 + 6311999 ] ], [ @@ -684,7 +719,7 @@ "contract": "CAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAD2KM", "key": { "ledger_key_nonce": { - "nonce": 4270020994084947596 + "nonce": 4837995959683129791 } }, "durability": "temporary" @@ -699,7 +734,7 @@ "contract": "CAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAD2KM", "key": { "ledger_key_nonce": { - "nonce": 4270020994084947596 + "nonce": 4837995959683129791 } }, "durability": "temporary", @@ -717,7 +752,7 @@ "contract": "CAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAD2KM", "key": { "ledger_key_nonce": { - "nonce": 4837995959683129791 + "nonce": 5541220902715666415 } }, "durability": "temporary" @@ -732,7 +767,7 @@ "contract": "CAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAD2KM", "key": { "ledger_key_nonce": { - "nonce": 4837995959683129791 + "nonce": 5541220902715666415 } }, "durability": "temporary", @@ -750,7 +785,7 @@ "contract": "CAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAD2KM", "key": { "ledger_key_nonce": { - "nonce": 5541220902715666415 + "nonce": 6391496069076573377 } }, "durability": "temporary" @@ -765,7 +800,7 @@ "contract": "CAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAD2KM", "key": { "ledger_key_nonce": { - "nonce": 5541220902715666415 + "nonce": 6391496069076573377 } }, "durability": "temporary", @@ -774,7 +809,7 @@ }, "ext": "v0" }, - 6311999 + 6346560 ] ], [ @@ -783,7 +818,7 @@ "contract": "CAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAD2KM", "key": { "ledger_key_nonce": { - "nonce": 7270604957039011794 + "nonce": 6517132746326325848 } }, "durability": "temporary" @@ -798,7 +833,7 @@ "contract": "CAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAD2KM", "key": { "ledger_key_nonce": { - "nonce": 7270604957039011794 + "nonce": 6517132746326325848 } }, "durability": "temporary", @@ -1880,7 +1915,7 @@ "contract": "CAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAK3IM", "key": { "ledger_key_nonce": { - "nonce": 2781962168096793370 + "nonce": 1301173170172112462 } }, "durability": "temporary" @@ -1895,7 +1930,7 @@ "contract": "CAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAK3IM", "key": { "ledger_key_nonce": { - "nonce": 2781962168096793370 + "nonce": 1301173170172112462 } }, "durability": "temporary", @@ -1913,7 +1948,7 @@ "contract": "CAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAK3IM", "key": { "ledger_key_nonce": { - "nonce": 3126073502131104533 + "nonce": 2307661404550649928 } }, "durability": "temporary" @@ -1928,7 +1963,7 @@ "contract": "CAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAK3IM", "key": { "ledger_key_nonce": { - "nonce": 3126073502131104533 + "nonce": 2307661404550649928 } }, "durability": "temporary", @@ -1946,7 +1981,7 @@ "contract": "CAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAK3IM", "key": { "ledger_key_nonce": { - "nonce": 6517132746326325848 + "nonce": 7270604957039011794 } }, "durability": "temporary" @@ -1961,7 +1996,7 @@ "contract": "CAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAK3IM", "key": { "ledger_key_nonce": { - "nonce": 6517132746326325848 + "nonce": 7270604957039011794 } }, "durability": "temporary", @@ -2099,7 +2134,7 @@ }, "durability": "persistent", "val": { - "u32": 0 + "u32": 1 } } }, @@ -2714,6 +2749,208 @@ 518400 ] ], + [ + { + "contract_data": { + "contract": "CAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAMDR4", + "key": { + "vec": [ + { + "symbol": "Loan" + }, + { + "u32": 4 + } + ] + }, + "durability": "persistent" + } + }, + [ + { + "last_modified_ledger_seq": 0, + "data": { + "contract_data": { + "ext": "v0", + "contract": "CAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAMDR4", + "key": { + "vec": [ + { + "symbol": "Loan" + }, + { + "u32": 4 + } + ] + }, + "durability": "persistent", + "val": { + "map": [ + { + "key": { + "symbol": "accrued_interest" + }, + "val": { + "i128": { + "hi": 0, + "lo": 0 + } + } + }, + { + "key": { + "symbol": "accrued_late_fee" + }, + "val": { + "i128": { + "hi": 0, + "lo": 0 + } + } + }, + { + "key": { + "symbol": "amount" + }, + "val": { + "i128": { + "hi": 0, + "lo": 1000 + } + } + }, + { + "key": { + "symbol": "borrower" + }, + "val": { + "address": "CAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAATYON" + } + }, + { + "key": { + "symbol": "collateral_amount" + }, + "val": { + "i128": { + "hi": 0, + "lo": 0 + } + } + }, + { + "key": { + "symbol": "due_date" + }, + "val": { + "u32": 0 + } + }, + { + "key": { + "symbol": "extension_count" + }, + "val": { + "u32": 0 + } + }, + { + "key": { + "symbol": "interest_paid" + }, + "val": { + "i128": { + "hi": 0, + "lo": 0 + } + } + }, + { + "key": { + "symbol": "interest_rate_bps" + }, + "val": { + "u32": 1200 + } + }, + { + "key": { + "symbol": "interest_residual" + }, + "val": { + "i128": { + "hi": 0, + "lo": 0 + } + } + }, + { + "key": { + "symbol": "last_interest_ledger" + }, + "val": { + "u32": 0 + } + }, + { + "key": { + "symbol": "last_late_fee_ledger" + }, + "val": { + "u32": 0 + } + }, + { + "key": { + "symbol": "late_fee_paid" + }, + "val": { + "i128": { + "hi": 0, + "lo": 0 + } + } + }, + { + "key": { + "symbol": "principal_paid" + }, + "val": { + "i128": { + "hi": 0, + "lo": 0 + } + } + }, + { + "key": { + "symbol": "status" + }, + "val": { + "vec": [ + { + "symbol": "Pending" + } + ] + } + }, + { + "key": { + "symbol": "term_ledgers" + }, + "val": { + "u32": 17280 + } + } + ] + } + } + }, + "ext": "v0" + }, + 518400 + ] + ], [ { "contract_data": { @@ -2802,6 +3039,9 @@ "vec": [ { "u32": 3 + }, + { + "u32": 4 } ] } @@ -2887,7 +3127,7 @@ ] }, "val": { - "u32": 3 + "u32": 4 } }, { @@ -3083,6 +3323,39 @@ 6311999 ] ], + [ + { + "contract_data": { + "contract": "CAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAATYON", + "key": { + "ledger_key_nonce": { + "nonce": 115220454072064130 + } + }, + "durability": "temporary" + } + }, + [ + { + "last_modified_ledger_seq": 0, + "data": { + "contract_data": { + "ext": "v0", + "contract": "CAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAATYON", + "key": { + "ledger_key_nonce": { + "nonce": 115220454072064130 + } + }, + "durability": "temporary", + "val": "void" + } + }, + "ext": "v0" + }, + 6311999 + ] + ], [ { "contract_data": { diff --git a/contracts/loan_manager/test_snapshots/test/test_overdue_partial_repayment_still_reduces_principal.1.json b/contracts/loan_manager/test_snapshots/test/test_overdue_partial_repayment_still_reduces_principal.1.json index e7430e74..0c29e9db 100644 --- a/contracts/loan_manager/test_snapshots/test/test_overdue_partial_repayment_still_reduces_principal.1.json +++ b/contracts/loan_manager/test_snapshots/test/test_overdue_partial_repayment_still_reduces_principal.1.json @@ -1229,7 +1229,7 @@ "val": { "i128": { "hi": 0, - "lo": 135 + "lo": 13 } } }, @@ -1240,7 +1240,7 @@ "val": { "i128": { "hi": 0, - "lo": 19 + "lo": 18 } } }, @@ -1297,7 +1297,7 @@ "val": { "i128": { "hi": 0, - "lo": 45 + "lo": 5 } } }, @@ -1343,7 +1343,7 @@ "val": { "i128": { "hi": 0, - "lo": 6 + "lo": 7 } } }, @@ -1354,7 +1354,7 @@ "val": { "i128": { "hi": 0, - "lo": 249 + "lo": 288 } } }, diff --git a/contracts/loan_manager/test_snapshots/test/test_overdue_repayment_charges_late_fee.1.json b/contracts/loan_manager/test_snapshots/test/test_overdue_repayment_charges_late_fee.1.json index 5ecf55e8..60737d21 100644 --- a/contracts/loan_manager/test_snapshots/test/test_overdue_repayment_charges_late_fee.1.json +++ b/contracts/loan_manager/test_snapshots/test/test_overdue_repayment_charges_late_fee.1.json @@ -1230,7 +1230,7 @@ "val": { "i128": { "hi": 0, - "lo": 135 + "lo": 13 } } }, @@ -1241,7 +1241,7 @@ "val": { "i128": { "hi": 0, - "lo": 19 + "lo": 18 } } }, @@ -1298,7 +1298,7 @@ "val": { "i128": { "hi": 0, - "lo": 45 + "lo": 5 } } }, @@ -1344,7 +1344,7 @@ "val": { "i128": { "hi": 0, - "lo": 6 + "lo": 7 } } }, @@ -1355,7 +1355,7 @@ "val": { "i128": { "hi": 0, - "lo": 249 + "lo": 288 } } }, diff --git a/contracts/loan_manager/test_snapshots/test/test_query_functions.1.json b/contracts/loan_manager/test_snapshots/test/test_query_functions.1.json index 7a64357e..5b94f16a 100644 --- a/contracts/loan_manager/test_snapshots/test/test_query_functions.1.json +++ b/contracts/loan_manager/test_snapshots/test/test_query_functions.1.json @@ -74,6 +74,7 @@ [], [], [], + [], [ [ "CAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAD2KM", diff --git a/contracts/multisig_governance/test_snapshots/test/cancel_allows_reproposal_after_cooldown.1.json b/contracts/multisig_governance/test_snapshots/test/cancel_allows_reproposal_after_cooldown.1.json index 5968132e..92a9607e 100644 --- a/contracts/multisig_governance/test_snapshots/test/cancel_allows_reproposal_after_cooldown.1.json +++ b/contracts/multisig_governance/test_snapshots/test/cancel_allows_reproposal_after_cooldown.1.json @@ -54,38 +54,6 @@ } ] ], - [ - [ - "CAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAFCT4", - { - "function": { - "contract_fn": { - "contract_address": "CAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAD2KM", - "function_name": "propose_admin_transfer", - "args": [ - { - "address": "CAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAMDR4" - }, - { - "vec": [ - { - "address": "CAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAITA4" - } - ] - }, - { - "u32": 1 - }, - { - "u64": 86400 - } - ] - } - }, - "sub_invocations": [] - } - ] - ], [] ], "ledger": { @@ -142,7 +110,7 @@ "symbol": "COUNT" }, "val": { - "u32": 2 + "u32": 1 } }, { @@ -164,7 +132,7 @@ "symbol": "executable_after" }, "val": { - "u64": 91001 + "u64": 87400 } }, { @@ -172,7 +140,7 @@ "symbol": "id" }, "val": { - "u32": 2 + "u32": 1 } }, { @@ -180,7 +148,7 @@ "symbol": "proposed_admin" }, "val": { - "address": "CAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAMDR4" + "address": "CAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAK3IM" } }, { @@ -188,7 +156,7 @@ "symbol": "proposed_at" }, "val": { - "u64": 4601 + "u64": 1000 } }, { @@ -208,7 +176,7 @@ "symbol": "status" }, "val": { - "u32": 0 + "u32": 1 } }, { @@ -281,39 +249,6 @@ 10000999 ] ], - [ - { - "contract_data": { - "contract": "CAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAFCT4", - "key": { - "ledger_key_nonce": { - "nonce": 1033654523790656264 - } - }, - "durability": "temporary" - } - }, - [ - { - "last_modified_ledger_seq": 0, - "data": { - "contract_data": { - "ext": "v0", - "contract": "CAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAFCT4", - "key": { - "ledger_key_nonce": { - "nonce": 1033654523790656264 - } - }, - "durability": "temporary", - "val": "void" - } - }, - "ext": "v0" - }, - 10000999 - ] - ], [ { "contract_data": { diff --git a/contracts/multisig_governance/test_snapshots/test/cancel_enforces_reproposal_cooldown.1.json b/contracts/multisig_governance/test_snapshots/test/cancel_enforces_reproposal_cooldown.1.json index 08182088..47d52d5d 100644 --- a/contracts/multisig_governance/test_snapshots/test/cancel_enforces_reproposal_cooldown.1.json +++ b/contracts/multisig_governance/test_snapshots/test/cancel_enforces_reproposal_cooldown.1.json @@ -54,7 +54,38 @@ } ] ], - [] + [ + [ + "CAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAFCT4", + { + "function": { + "contract_fn": { + "contract_address": "CAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAD2KM", + "function_name": "propose_admin_transfer", + "args": [ + { + "address": "CAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAMDR4" + }, + { + "vec": [ + { + "address": "CAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAITA4" + } + ] + }, + { + "u32": 1 + }, + { + "u64": 86400 + } + ] + } + }, + "sub_invocations": [] + } + ] + ] ], "ledger": { "protocol_version": 22, @@ -110,7 +141,7 @@ "symbol": "COUNT" }, "val": { - "u32": 1 + "u32": 2 } }, { @@ -140,7 +171,7 @@ "symbol": "id" }, "val": { - "u32": 1 + "u32": 2 } }, { @@ -148,7 +179,7 @@ "symbol": "proposed_admin" }, "val": { - "address": "CAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAK3IM" + "address": "CAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAMDR4" } }, { @@ -176,7 +207,7 @@ "symbol": "status" }, "val": { - "u32": 1 + "u32": 0 } }, { @@ -249,6 +280,39 @@ 10000999 ] ], + [ + { + "contract_data": { + "contract": "CAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAFCT4", + "key": { + "ledger_key_nonce": { + "nonce": 1033654523790656264 + } + }, + "durability": "temporary" + } + }, + [ + { + "last_modified_ledger_seq": 0, + "data": { + "contract_data": { + "ext": "v0", + "contract": "CAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAFCT4", + "key": { + "ledger_key_nonce": { + "nonce": 1033654523790656264 + } + }, + "durability": "temporary", + "val": "void" + } + }, + "ext": "v0" + }, + 10000999 + ] + ], [ { "contract_data": { @@ -337,5 +401,82 @@ ] ] }, - "events": [] + "events": [ + { + "event": { + "ext": "v0", + "contract_id": "0000000000000000000000000000000000000000000000000000000000000001", + "type_": "contract", + "body": { + "v0": { + "topics": [ + { + "symbol": "GovProp" + }, + { + "address": "CAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAFCT4" + } + ], + "data": { + "map": [ + { + "key": { + "symbol": "executable_after" + }, + "val": { + "u64": 87400 + } + }, + { + "key": { + "symbol": "proposed_admin" + }, + "val": { + "address": "CAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAMDR4" + } + }, + { + "key": { + "symbol": "proposed_by" + }, + "val": { + "address": "CAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAFCT4" + } + }, + { + "key": { + "symbol": "signers" + }, + "val": { + "vec": [ + { + "address": "CAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAITA4" + } + ] + } + }, + { + "key": { + "symbol": "threshold" + }, + "val": { + "u32": 1 + } + }, + { + "key": { + "symbol": "timestamp" + }, + "val": { + "u64": 1000 + } + } + ] + } + } + } + }, + "failed_call": false + } + ] } \ No newline at end of file diff --git a/contracts/multisig_governance/test_snapshots/test/finalize_before_timelock_panics.1.json b/contracts/multisig_governance/test_snapshots/test/finalize_before_timelock_panics.1.json index d1cb21ae..46885373 100644 --- a/contracts/multisig_governance/test_snapshots/test/finalize_before_timelock_panics.1.json +++ b/contracts/multisig_governance/test_snapshots/test/finalize_before_timelock_panics.1.json @@ -58,7 +58,25 @@ } ] ], - [] + [ + [ + "CAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAMDR4", + { + "function": { + "contract_fn": { + "contract_address": "CAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAD2KM", + "function_name": "finalize_admin_transfer", + "args": [ + { + "address": "CAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAMDR4" + } + ] + } + }, + "sub_invocations": [] + } + ] + ] ], "ledger": { "protocol_version": 22, @@ -98,101 +116,23 @@ "symbol": "ADMIN" }, "val": { - "address": "CAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAFCT4" + "address": "CAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAK3IM" } }, { "key": { - "symbol": "COUNT" + "symbol": "CANCEL_AT" }, "val": { - "u32": 1 + "u64": 87399 } }, { "key": { - "symbol": "PENDING" + "symbol": "COUNT" }, "val": { - "map": [ - { - "key": { - "symbol": "approvals" - }, - "val": { - "map": [ - { - "key": { - "address": "CAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAITA4" - }, - "val": { - "bool": true - } - } - ] - } - }, - { - "key": { - "symbol": "executable_after" - }, - "val": { - "u64": 87400 - } - }, - { - "key": { - "symbol": "id" - }, - "val": { - "u32": 1 - } - }, - { - "key": { - "symbol": "proposed_admin" - }, - "val": { - "address": "CAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAK3IM" - } - }, - { - "key": { - "symbol": "proposed_at" - }, - "val": { - "u64": 1000 - } - }, - { - "key": { - "symbol": "signers" - }, - "val": { - "vec": [ - { - "address": "CAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAITA4" - } - ] - } - }, - { - "key": { - "symbol": "status" - }, - "val": { - "u32": 0 - } - }, - { - "key": { - "symbol": "threshold" - }, - "val": { - "u32": 1 - } - } - ] + "u32": 1 } }, { @@ -276,7 +216,16 @@ "executable": { "wasm": "e3b0c44298fc1c149afbf4c8996fb92427ae41e4649b934ca495991b7852b855" }, - "storage": null + "storage": [ + { + "key": { + "symbol": "admin" + }, + "val": { + "address": "CAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAK3IM" + } + } + ] } } } @@ -319,6 +268,39 @@ 10000999 ] ], + [ + { + "contract_data": { + "contract": "CAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAMDR4", + "key": { + "ledger_key_nonce": { + "nonce": 1033654523790656264 + } + }, + "durability": "temporary" + } + }, + [ + { + "last_modified_ledger_seq": 0, + "data": { + "contract_data": { + "ext": "v0", + "contract": "CAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAMDR4", + "key": { + "ledger_key_nonce": { + "nonce": 1033654523790656264 + } + }, + "durability": "temporary", + "val": "void" + } + }, + "ext": "v0" + }, + 10000999 + ] + ], [ { "contract_code": { @@ -342,5 +324,62 @@ ] ] }, - "events": [] + "events": [ + { + "event": { + "ext": "v0", + "contract_id": "0000000000000000000000000000000000000000000000000000000000000001", + "type_": "contract", + "body": { + "v0": { + "topics": [ + { + "symbol": "GovFin" + }, + { + "address": "CAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAK3IM" + } + ], + "data": { + "map": [ + { + "key": { + "symbol": "approval_count" + }, + "val": { + "u32": 1 + } + }, + { + "key": { + "symbol": "finalized_by" + }, + "val": { + "address": "CAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAMDR4" + } + }, + { + "key": { + "symbol": "new_admin" + }, + "val": { + "address": "CAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAK3IM" + } + }, + { + "key": { + "symbol": "timestamp" + }, + "val": { + "u64": 87399 + } + } + ] + } + } + } + }, + "failed_call": false + } + ] } \ No newline at end of file diff --git a/contracts/multisig_governance/test_snapshots/test/finalize_succeeds_and_updates_local_and_remote_state.1.json b/contracts/multisig_governance/test_snapshots/test/finalize_succeeds_and_updates_local_and_remote_state.1.json index 6736e3b6..78ba9f9f 100644 --- a/contracts/multisig_governance/test_snapshots/test/finalize_succeeds_and_updates_local_and_remote_state.1.json +++ b/contracts/multisig_governance/test_snapshots/test/finalize_succeeds_and_updates_local_and_remote_state.1.json @@ -58,27 +58,6 @@ } ] ], - [ - [ - "CAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAFCT4", - { - "function": { - "contract_fn": { - "contract_address": "CAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAD2KM", - "function_name": "finalize_admin_transfer", - "args": [ - { - "address": "CAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAFCT4" - } - ] - } - }, - "sub_invocations": [] - } - ] - ], - [], - [], [] ], "ledger": { @@ -119,23 +98,101 @@ "symbol": "ADMIN" }, "val": { - "address": "CAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAITA4" + "address": "CAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAFCT4" } }, { "key": { - "symbol": "CANCEL_AT" + "symbol": "COUNT" }, "val": { - "u64": 87401 + "u32": 1 } }, { "key": { - "symbol": "COUNT" + "symbol": "PENDING" }, "val": { - "u32": 1 + "map": [ + { + "key": { + "symbol": "approvals" + }, + "val": { + "map": [ + { + "key": { + "address": "CAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAK3IM" + }, + "val": { + "bool": true + } + } + ] + } + }, + { + "key": { + "symbol": "executable_after" + }, + "val": { + "u64": 87400 + } + }, + { + "key": { + "symbol": "id" + }, + "val": { + "u32": 1 + } + }, + { + "key": { + "symbol": "proposed_admin" + }, + "val": { + "address": "CAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAITA4" + } + }, + { + "key": { + "symbol": "proposed_at" + }, + "val": { + "u64": 1000 + } + }, + { + "key": { + "symbol": "signers" + }, + "val": { + "vec": [ + { + "address": "CAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAK3IM" + } + ] + } + }, + { + "key": { + "symbol": "status" + }, + "val": { + "u32": 0 + } + }, + { + "key": { + "symbol": "threshold" + }, + "val": { + "u32": 1 + } + } + ] } }, { @@ -197,39 +254,6 @@ 10000999 ] ], - [ - { - "contract_data": { - "contract": "CAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAFCT4", - "key": { - "ledger_key_nonce": { - "nonce": 1033654523790656264 - } - }, - "durability": "temporary" - } - }, - [ - { - "last_modified_ledger_seq": 0, - "data": { - "contract_data": { - "ext": "v0", - "contract": "CAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAFCT4", - "key": { - "ledger_key_nonce": { - "nonce": 1033654523790656264 - } - }, - "durability": "temporary", - "val": "void" - } - }, - "ext": "v0" - }, - 10000999 - ] - ], [ { "contract_data": { @@ -252,16 +276,7 @@ "executable": { "wasm": "e3b0c44298fc1c149afbf4c8996fb92427ae41e4649b934ca495991b7852b855" }, - "storage": [ - { - "key": { - "symbol": "admin" - }, - "val": { - "address": "CAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAITA4" - } - } - ] + "storage": null } } } diff --git a/contracts/multisig_governance/test_snapshots/test/finalize_works_within_ttl.1.json b/contracts/multisig_governance/test_snapshots/test/finalize_works_within_ttl.1.json index db3f28f2..78ba9f9f 100644 --- a/contracts/multisig_governance/test_snapshots/test/finalize_works_within_ttl.1.json +++ b/contracts/multisig_governance/test_snapshots/test/finalize_works_within_ttl.1.json @@ -58,26 +58,6 @@ } ] ], - [ - [ - "CAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAFCT4", - { - "function": { - "contract_fn": { - "contract_address": "CAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAD2KM", - "function_name": "finalize_admin_transfer", - "args": [ - { - "address": "CAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAFCT4" - } - ] - } - }, - "sub_invocations": [] - } - ] - ], - [], [] ], "ledger": { @@ -118,23 +98,101 @@ "symbol": "ADMIN" }, "val": { - "address": "CAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAITA4" + "address": "CAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAFCT4" } }, { "key": { - "symbol": "CANCEL_AT" + "symbol": "COUNT" }, "val": { - "u64": 87401 + "u32": 1 } }, { "key": { - "symbol": "COUNT" + "symbol": "PENDING" }, "val": { - "u32": 1 + "map": [ + { + "key": { + "symbol": "approvals" + }, + "val": { + "map": [ + { + "key": { + "address": "CAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAK3IM" + }, + "val": { + "bool": true + } + } + ] + } + }, + { + "key": { + "symbol": "executable_after" + }, + "val": { + "u64": 87400 + } + }, + { + "key": { + "symbol": "id" + }, + "val": { + "u32": 1 + } + }, + { + "key": { + "symbol": "proposed_admin" + }, + "val": { + "address": "CAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAITA4" + } + }, + { + "key": { + "symbol": "proposed_at" + }, + "val": { + "u64": 1000 + } + }, + { + "key": { + "symbol": "signers" + }, + "val": { + "vec": [ + { + "address": "CAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAK3IM" + } + ] + } + }, + { + "key": { + "symbol": "status" + }, + "val": { + "u32": 0 + } + }, + { + "key": { + "symbol": "threshold" + }, + "val": { + "u32": 1 + } + } + ] } }, { @@ -196,39 +254,6 @@ 10000999 ] ], - [ - { - "contract_data": { - "contract": "CAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAFCT4", - "key": { - "ledger_key_nonce": { - "nonce": 1033654523790656264 - } - }, - "durability": "temporary" - } - }, - [ - { - "last_modified_ledger_seq": 0, - "data": { - "contract_data": { - "ext": "v0", - "contract": "CAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAFCT4", - "key": { - "ledger_key_nonce": { - "nonce": 1033654523790656264 - } - }, - "durability": "temporary", - "val": "void" - } - }, - "ext": "v0" - }, - 10000999 - ] - ], [ { "contract_data": { @@ -251,16 +276,7 @@ "executable": { "wasm": "e3b0c44298fc1c149afbf4c8996fb92427ae41e4649b934ca495991b7852b855" }, - "storage": [ - { - "key": { - "symbol": "admin" - }, - "val": { - "address": "CAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAITA4" - } - } - ] + "storage": null } } } diff --git a/contracts/multisig_governance/test_snapshots/test/get_signers_returns_signer_list.1.json b/contracts/multisig_governance/test_snapshots/test/get_signers_returns_signer_list.1.json index f588a2c5..7216365b 100644 --- a/contracts/multisig_governance/test_snapshots/test/get_signers_returns_signer_list.1.json +++ b/contracts/multisig_governance/test_snapshots/test/get_signers_returns_signer_list.1.json @@ -4,6 +4,7 @@ "nonce": 0 }, "auth": [ + [], [], [], [ @@ -86,7 +87,7 @@ }, { "key": { - "symbol": "PCOUNT" + "symbol": "COUNT" }, "val": { "u32": 1 @@ -114,6 +115,14 @@ "u64": 86400 } }, + { + "key": { + "symbol": "id" + }, + "val": { + "u32": 1 + } + }, { "key": { "symbol": "proposed_admin" @@ -122,6 +131,14 @@ "address": "CAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAMDR4" } }, + { + "key": { + "symbol": "proposed_at" + }, + "val": { + "u64": 0 + } + }, { "key": { "symbol": "signers" @@ -137,6 +154,14 @@ ] } }, + { + "key": { + "symbol": "status" + }, + "val": { + "u32": 0 + } + }, { "key": { "symbol": "threshold" @@ -155,6 +180,14 @@ "val": { "address": "CAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAHK3M" } + }, + { + "key": { + "symbol": "VERSION" + }, + "val": { + "u32": 1 + } } ] } @@ -199,6 +232,38 @@ 6311999 ] ], + [ + { + "contract_data": { + "contract": "CAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAHK3M", + "key": "ledger_key_contract_instance", + "durability": "persistent" + } + }, + [ + { + "last_modified_ledger_seq": 0, + "data": { + "contract_data": { + "ext": "v0", + "contract": "CAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAHK3M", + "key": "ledger_key_contract_instance", + "durability": "persistent", + "val": { + "contract_instance": { + "executable": { + "wasm": "e3b0c44298fc1c149afbf4c8996fb92427ae41e4649b934ca495991b7852b855" + }, + "storage": null + } + } + } + }, + "ext": "v0" + }, + 4095 + ] + ], [ { "contract_code": { diff --git a/contracts/multisig_governance/test_snapshots/test/get_threshold_returns_pending_threshold.1.json b/contracts/multisig_governance/test_snapshots/test/get_threshold_returns_pending_threshold.1.json index bbe68440..64daffcd 100644 --- a/contracts/multisig_governance/test_snapshots/test/get_threshold_returns_pending_threshold.1.json +++ b/contracts/multisig_governance/test_snapshots/test/get_threshold_returns_pending_threshold.1.json @@ -4,6 +4,7 @@ "nonce": 0 }, "auth": [ + [], [], [], [ @@ -83,7 +84,7 @@ }, { "key": { - "symbol": "PCOUNT" + "symbol": "COUNT" }, "val": { "u32": 1 @@ -111,6 +112,14 @@ "u64": 86400 } }, + { + "key": { + "symbol": "id" + }, + "val": { + "u32": 1 + } + }, { "key": { "symbol": "proposed_admin" @@ -119,6 +128,14 @@ "address": "CAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAK3IM" } }, + { + "key": { + "symbol": "proposed_at" + }, + "val": { + "u64": 0 + } + }, { "key": { "symbol": "signers" @@ -131,6 +148,14 @@ ] } }, + { + "key": { + "symbol": "status" + }, + "val": { + "u32": 0 + } + }, { "key": { "symbol": "threshold" @@ -149,6 +174,14 @@ "val": { "address": "CAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAHK3M" } + }, + { + "key": { + "symbol": "VERSION" + }, + "val": { + "u32": 1 + } } ] } @@ -193,6 +226,38 @@ 6311999 ] ], + [ + { + "contract_data": { + "contract": "CAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAHK3M", + "key": "ledger_key_contract_instance", + "durability": "persistent" + } + }, + [ + { + "last_modified_ledger_seq": 0, + "data": { + "contract_data": { + "ext": "v0", + "contract": "CAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAHK3M", + "key": "ledger_key_contract_instance", + "durability": "persistent", + "val": { + "contract_instance": { + "executable": { + "wasm": "e3b0c44298fc1c149afbf4c8996fb92427ae41e4649b934ca495991b7852b855" + }, + "storage": null + } + } + } + }, + "ext": "v0" + }, + 4095 + ] + ], [ { "contract_code": { diff --git a/contracts/multisig_governance/test_snapshots/test/has_approved_tracks_approvals.1.json b/contracts/multisig_governance/test_snapshots/test/has_approved_tracks_approvals.1.json index 60c74743..3d3aaa74 100644 --- a/contracts/multisig_governance/test_snapshots/test/has_approved_tracks_approvals.1.json +++ b/contracts/multisig_governance/test_snapshots/test/has_approved_tracks_approvals.1.json @@ -4,6 +4,7 @@ "nonce": 0 }, "auth": [ + [], [], [], [ @@ -129,7 +130,7 @@ }, { "key": { - "symbol": "PCOUNT" + "symbol": "COUNT" }, "val": { "u32": 1 @@ -174,6 +175,14 @@ "u64": 86400 } }, + { + "key": { + "symbol": "id" + }, + "val": { + "u32": 1 + } + }, { "key": { "symbol": "proposed_admin" @@ -182,6 +191,14 @@ "address": "CAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAMDR4" } }, + { + "key": { + "symbol": "proposed_at" + }, + "val": { + "u64": 0 + } + }, { "key": { "symbol": "signers" @@ -197,6 +214,14 @@ ] } }, + { + "key": { + "symbol": "status" + }, + "val": { + "u32": 0 + } + }, { "key": { "symbol": "threshold" @@ -215,6 +240,14 @@ "val": { "address": "CAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAHK3M" } + }, + { + "key": { + "symbol": "VERSION" + }, + "val": { + "u32": 1 + } } ] } @@ -259,6 +292,38 @@ 6311999 ] ], + [ + { + "contract_data": { + "contract": "CAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAHK3M", + "key": "ledger_key_contract_instance", + "durability": "persistent" + } + }, + [ + { + "last_modified_ledger_seq": 0, + "data": { + "contract_data": { + "ext": "v0", + "contract": "CAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAHK3M", + "key": "ledger_key_contract_instance", + "durability": "persistent", + "val": { + "contract_instance": { + "executable": { + "wasm": "e3b0c44298fc1c149afbf4c8996fb92427ae41e4649b934ca495991b7852b855" + }, + "storage": null + } + } + } + }, + "ext": "v0" + }, + 4095 + ] + ], [ { "contract_data": { diff --git a/contracts/multisig_governance/test_snapshots/test/proposal_count_increments.1.json b/contracts/multisig_governance/test_snapshots/test/proposal_count_increments.1.json index f72aed0f..6f138cc5 100644 --- a/contracts/multisig_governance/test_snapshots/test/proposal_count_increments.1.json +++ b/contracts/multisig_governance/test_snapshots/test/proposal_count_increments.1.json @@ -7,6 +7,7 @@ [], [], [], + [], [ [ "CAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAFCT4", @@ -56,49 +57,17 @@ ] ], [], - [ - [ - "CAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAFCT4", - { - "function": { - "contract_fn": { - "contract_address": "CAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAD2KM", - "function_name": "propose_admin_transfer", - "args": [ - { - "address": "CAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAOLZM" - }, - { - "vec": [ - { - "address": "CAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAMDR4" - } - ] - }, - { - "u32": 1 - }, - { - "u64": 86400 - } - ] - } - }, - "sub_invocations": [] - } - ] - ], [] ], "ledger": { "protocol_version": 22, - "sequence_number": 0, - "timestamp": 0, + "sequence_number": 1000, + "timestamp": 4601, "network_id": "0000000000000000000000000000000000000000000000000000000000000000", - "base_reserve": 0, - "min_persistent_entry_ttl": 4096, - "min_temp_entry_ttl": 16, - "max_entry_ttl": 6312000, + "base_reserve": 5000000, + "min_persistent_entry_ttl": 1000000, + "min_temp_entry_ttl": 1000000, + "max_entry_ttl": 10000000, "ledger_entries": [ [ { @@ -133,10 +102,18 @@ }, { "key": { - "symbol": "PCOUNT" + "symbol": "CANCEL_AT" }, "val": { - "u32": 2 + "u64": 0 + } + }, + { + "key": { + "symbol": "COUNT" + }, + "val": { + "u32": 1 } }, { @@ -161,12 +138,28 @@ "u64": 86400 } }, + { + "key": { + "symbol": "id" + }, + "val": { + "u32": 1 + } + }, { "key": { "symbol": "proposed_admin" }, "val": { - "address": "CAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAOLZM" + "address": "CAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAK3IM" + } + }, + { + "key": { + "symbol": "proposed_at" + }, + "val": { + "u64": 0 } }, { @@ -176,11 +169,19 @@ "val": { "vec": [ { - "address": "CAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAMDR4" + "address": "CAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAITA4" } ] } }, + { + "key": { + "symbol": "status" + }, + "val": { + "u32": 1 + } + }, { "key": { "symbol": "threshold" @@ -199,6 +200,14 @@ "val": { "address": "CAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAHK3M" } + }, + { + "key": { + "symbol": "VERSION" + }, + "val": { + "u32": 1 + } } ] } @@ -249,7 +258,7 @@ "contract": "CAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAFCT4", "key": { "ledger_key_nonce": { - "nonce": 1033654523790656264 + "nonce": 5541220902715666415 } }, "durability": "temporary" @@ -264,7 +273,7 @@ "contract": "CAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAFCT4", "key": { "ledger_key_nonce": { - "nonce": 1033654523790656264 + "nonce": 5541220902715666415 } }, "durability": "temporary", @@ -279,13 +288,9 @@ [ { "contract_data": { - "contract": "CAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAFCT4", - "key": { - "ledger_key_nonce": { - "nonce": 5541220902715666415 - } - }, - "durability": "temporary" + "contract": "CAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAHK3M", + "key": "ledger_key_contract_instance", + "durability": "persistent" } }, [ @@ -294,19 +299,22 @@ "data": { "contract_data": { "ext": "v0", - "contract": "CAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAFCT4", - "key": { - "ledger_key_nonce": { - "nonce": 5541220902715666415 + "contract": "CAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAHK3M", + "key": "ledger_key_contract_instance", + "durability": "persistent", + "val": { + "contract_instance": { + "executable": { + "wasm": "e3b0c44298fc1c149afbf4c8996fb92427ae41e4649b934ca495991b7852b855" + }, + "storage": null } - }, - "durability": "temporary", - "val": "void" + } } }, "ext": "v0" }, - 6311999 + 4095 ] ], [ diff --git a/contracts/remittance_nft/src/lib.rs b/contracts/remittance_nft/src/lib.rs index 65835d81..c33dbe41 100644 --- a/contracts/remittance_nft/src/lib.rs +++ b/contracts/remittance_nft/src/lib.rs @@ -726,7 +726,7 @@ impl RemittanceNFT { let old_score = metadata.score; let decreased = old_score.saturating_sub(penalty_points); - let new_score = decreased.min(Self::MIN_CREDIT_SCORE); + let new_score = decreased.max(Self::MIN_CREDIT_SCORE); if new_score == old_score { return; } diff --git a/frontend/src/app/hooks/useApi.ts b/frontend/src/app/hooks/useApi.ts index b728fb79..fe8b2874 100644 --- a/frontend/src/app/hooks/useApi.ts +++ b/frontend/src/app/hooks/useApi.ts @@ -1599,10 +1599,11 @@ export function useRepayLoan() { (old: LoanDetails | undefined) => { if (!old) return old; const newOwed = Math.max(0, old.totalOwed - amount); + const newRepaid = old.totalRepaid + amount; return { ...old, totalOwed: newOwed, - totalRepaid: old.totalRepaid - amount, + totalRepaid: newRepaid, status: newOwed <= 0 ? ("repaid" as const) : old.status, }; }, @@ -1757,7 +1758,7 @@ export function useWithdrawFromPool() { // Optimistically update pool stats queryClient.setQueryData(queryKeys.pool.stats(), (old: PoolStats | undefined) => { if (!old) return old; - return { ...old, totalDeposits: Math.max(0, old.totalDeposits + amount) }; + return { ...old, totalDeposits: Math.max(0, old.totalDeposits - amount) }; }); // Optimistically update depositor portfolio diff --git a/frontend/src/app/stores/useGamificationStore.ts b/frontend/src/app/stores/useGamificationStore.ts index ad8c98fb..40fe66b2 100644 --- a/frontend/src/app/stores/useGamificationStore.ts +++ b/frontend/src/app/stores/useGamificationStore.ts @@ -209,19 +209,38 @@ export const useGamificationStore = create()( addXP: (amount, reason) => { const currentXP = get().xp; + const currentLevel = get().level; const newXP = currentXP + amount; + const newLevel = calculateLevel(newXP); - set( - { - xp: newXP, - recentXPGain: { amount, reason: reason || "", id: Date.now() }, - }, - false, - `gamification/addXP:${reason || "unknown"}`, - ); - - // Check for level up - get().checkLevelUp(); + if (newLevel > currentLevel) { + const levelUpReward = LEVEL_THRESHOLDS.find((t) => t.level === newLevel); + set( + { + xp: newXP, + recentXPGain: { amount, reason: reason || "", id: Date.now() }, + ...(levelUpReward + ? { + level: newLevel, + kingdomTitle: levelUpReward.title, + showLevelUpModal: true, + pendingLevelUp: levelUpReward, + } + : {}), + }, + false, + `gamification/addXP:${reason || "unknown"}`, + ); + } else { + set( + { + xp: newXP, + recentXPGain: { amount, reason: reason || "", id: Date.now() }, + }, + false, + `gamification/addXP:${reason || "unknown"}`, + ); + } }, clearRecentXPGain: () => @@ -236,7 +255,7 @@ export const useGamificationStore = create()( const { xp, level } = get(); const newLevel = calculateLevel(xp); - if (newLevel >= level) { + if (newLevel > level) { const levelUpReward = LEVEL_THRESHOLDS.find((t) => t.level === newLevel); if (levelUpReward) { set( diff --git a/frontend/src/app/utils/amount.ts b/frontend/src/app/utils/amount.ts index 90219ecf..93dcaa49 100644 --- a/frontend/src/app/utils/amount.ts +++ b/frontend/src/app/utils/amount.ts @@ -58,7 +58,7 @@ export function toStroops(value: string, decimals = STROOP_DECIMALS): bigint | n } const [whole = "0", fraction = ""] = value.split("."); - const normalizedFraction = fraction.padStart(decimals, "0"); + const normalizedFraction = fraction.padEnd(decimals, "0").slice(0, decimals); try { // Scale by the requested precision, not the fixed 7-decimal stroop scale, diff --git a/frontend/src/app/utils/csv.ts b/frontend/src/app/utils/csv.ts index 6931b504..1a227d35 100644 --- a/frontend/src/app/utils/csv.ts +++ b/frontend/src/app/utils/csv.ts @@ -2,7 +2,7 @@ export type CsvRow = Record Date: Wed, 29 Jul 2026 16:29:43 +0100 Subject: [PATCH 3/3] fix: resolve lint errors - unused vars, prettier formatting --- backend/src/__tests__/security-issues.test.ts | 5 +--- backend/src/app.ts | 2 +- backend/src/controllers/indexerController.ts | 16 ------------- .../src/controllers/remittanceController.ts | 8 +------ .../controllers/transactionController.test.ts | 12 +++------- .../src/controllers/transactionController.ts | 2 +- backend/src/routes/statusRoutes.ts | 2 +- frontend/e2e/README.md | 24 +++++++++---------- 8 files changed, 20 insertions(+), 51 deletions(-) diff --git a/backend/src/__tests__/security-issues.test.ts b/backend/src/__tests__/security-issues.test.ts index c953efda..a5fce39c 100644 --- a/backend/src/__tests__/security-issues.test.ts +++ b/backend/src/__tests__/security-issues.test.ts @@ -1,4 +1,4 @@ -import { describe, it, expect, beforeAll, vi } from '@jest/globals'; +import { describe, it, expect, beforeAll } from '@jest/globals'; import { Keypair } from '@stellar/stellar-sdk'; import * as authService from '../services/authService.js'; import { resolveRoleForWallet } from '../auth/rbac.js'; @@ -15,8 +15,6 @@ describe('Security Issues - Critical Fixes', () => { // ───────────────────────────────────────────────────────────────────────── describe('Issue #1359: JWT Expiration Validation', () => { it('should reject expired tokens', () => { - const keypair = Keypair.random(); - // Create a token that's already expired const expiredToken = 'eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJleHAiOjE2MDAwMDAwMDB9.invalid'; @@ -40,7 +38,6 @@ describe('Security Issues - Critical Fixes', () => { it('should enforce expiration claim during verification', () => { // This test verifies that ignoreExpiration is NOT set to true // by checking that the JWT library enforces exp claim - const secret = process.env.JWT_SECRET!; const token = authService.generateJwtToken(Keypair.random().publicKey()); // The verifyJwtToken should respect the exp claim diff --git a/backend/src/app.ts b/backend/src/app.ts index c0ab9dfb..98241219 100644 --- a/backend/src/app.ts +++ b/backend/src/app.ts @@ -29,7 +29,7 @@ import { errorHandler } from './middleware/errorHandler.js'; import { metricsHandler, metricsMiddleware } from './middleware/metrics.js'; import { requestLogger } from './middleware/requestLogger.js'; import { requestIdMiddleware } from './middleware/requestId.js'; -import { pauseGuard, initializePauseState } from './middleware/pauseGuard.js'; +import { pauseGuard } from './middleware/pauseGuard.js'; import { asyncHandler } from './utils/asyncHandler.js'; import { AppError } from './errors/AppError.js'; const app = express(); diff --git a/backend/src/controllers/indexerController.ts b/backend/src/controllers/indexerController.ts index 769c4458..4cc78fa1 100644 --- a/backend/src/controllers/indexerController.ts +++ b/backend/src/controllers/indexerController.ts @@ -2,14 +2,12 @@ import type { Request, Response } from 'express'; import { xdr } from '@stellar/stellar-sdk'; import { query } from '../db/connection.js'; import { EventIndexer, type SorobanRawEvent } from '../services/eventIndexer.js'; -import { cacheService } from '../services/cacheService.js'; import { SUPPORTED_WEBHOOK_EVENT_TYPES, webhookService, type WebhookEventType, } from '../services/webhookService.js'; import { - buildKeysetClause, createCursorPaginatedResponse, decodeCursor, encodeCursor, @@ -85,20 +83,6 @@ const buildEventFilters = (req: Request, baseParams: unknown[], initialWhereClau return { params, whereClause }; }; -const buildEventsCacheKey = (scope: string, resourceId: string | number, req: Request) => - [ - 'events', - scope, - String(resourceId), - `limit:${req.query.limit ?? 'default'}`, - `cursor:${req.query.cursor ?? 'default'}`, - `offset:${req.query.offset ?? 'default'}`, - `sort:${req.query.sort ?? 'default'}`, - `status:${req.query.status ?? req.query.eventType ?? 'all'}`, - `date:${req.query.date_range ?? 'all'}`, - `amount:${req.query.amount_range ?? 'all'}`, - ].join(':'); - type QuarantineEventRow = { id: number; event_id: string; diff --git a/backend/src/controllers/remittanceController.ts b/backend/src/controllers/remittanceController.ts index 9f52a5f5..961a9805 100644 --- a/backend/src/controllers/remittanceController.ts +++ b/backend/src/controllers/remittanceController.ts @@ -151,13 +151,7 @@ export const getRemittances = asyncHandler(async (req: Request, res: Response) = queryParams: params, }); - const [result, countResult] = await Promise.all([ - query(queryText, params), - query( - `SELECT COUNT(*) as count FROM remittances WHERE ${whereClause.replace(` AND seq <= $${params.length - 1}`, '')}`, - params.slice(0, -2), - ), - ]); + const result = await query(queryText, params); const hasNext = result.rows.length > limit; const remittances = hasNext ? result.rows.slice(0, limit) : result.rows; diff --git a/backend/src/controllers/transactionController.test.ts b/backend/src/controllers/transactionController.test.ts index 6f05b6c9..25301731 100644 --- a/backend/src/controllers/transactionController.test.ts +++ b/backend/src/controllers/transactionController.test.ts @@ -4,21 +4,15 @@ import { MAX_LIMIT } from '../../controllers/transactionController'; describe('GET /api/transactions - Pagination Limits', () => { it('should cap page size to MAX_LIMIT when a larger limit is requested', async () => { - const res = await request(app) - .get('/api/transactions') - .query({ limit: 5000 }) - .expect(200); + const res = await request(app).get('/api/transactions').query({ limit: 5000 }).expect(200); expect(res.body.pagination.limit).toBe(MAX_LIMIT); // Expect 100 expect(res.body.data.length).toBeLessThanOrEqual(MAX_LIMIT); }); it('should use requested limit if under MAX_LIMIT', async () => { - const res = await request(app) - .get('/api/transactions') - .query({ limit: 50 }) - .expect(200); + const res = await request(app).get('/api/transactions').query({ limit: 50 }).expect(200); expect(res.body.pagination.limit).toBe(50); }); -}); \ No newline at end of file +}); diff --git a/backend/src/controllers/transactionController.ts b/backend/src/controllers/transactionController.ts index f4b9685c..c66f7c6c 100644 --- a/backend/src/controllers/transactionController.ts +++ b/backend/src/controllers/transactionController.ts @@ -94,4 +94,4 @@ export async function getTransactions(req: Request, res: Response): Promise