This implementation adds secure client account migration functionality to the Talenttrust escrow contract. The migration follows a two-step proposal + confirmation flow to ensure no unauthorized takeover of contract authority.
- Proposal Phase: Current client can propose migration to a new address
- Confirmation Phase: Proposed client must confirm the migration
- Finalization: Atomic update of contract client address
- Cancellation: Current client can cancel pending migration
- Expiration: Migrations expire after TTL to prevent stale proposals
- Authorization: Only current client can propose/cancel migration
- Confirmation: Only proposed client can confirm migration
- Status Restrictions: Migration only allowed in
CreatedandFundedstates - Duplicate Prevention: No concurrent migrations allowed
- Same Address Protection: Cannot migrate to same address
- Atomic Operations: Migration finalization is atomic
- Audit Trail: Full event emissions for all migration steps
#[contracttype]
#[derive(Clone, Debug, Eq, PartialEq)]
pub struct PendingClientMigration {
pub current_client: Address,
pub proposed_client: Address,
pub proposed_client_confirmed: bool,
pub requested_at_ledger: u32,
pub expires_at_ledger: u32,
}enum DataKey {
// ... existing keys
PendingClientMigration(u32),
}-
request_client_migration(env, contract_id, proposed_client) -> bool
- Propose migration to new address
- Requires current client authorization
- Emits
client_migration_proposedevent
-
confirm_client_migration(env, contract_id) -> bool
- Confirm migration by proposed client
- Requires proposed client authorization
- Emits
client_migration_confirmedevent
-
finalize_client_migration(env, contract_id) -> bool
- Finalize migration (atomic update)
- Updates contract client address
- Emits
client_migration_finalizedevent
-
cancel_client_migration(env, contract_id) -> bool
- Cancel pending migration
- Requires current client authorization
- Emits
client_migration_cancelledevent
-
get_pending_client_migration(env, contract_id) -> PendingClientMigration
- Get pending migration information
-
has_pending_client_migration(env, contract_id) -> bool
- Check if migration is pending
Migration is only allowed in these contract statuses:
Created- Contract not yet fundedFunded- Contract funded but not completed
Migration is NOT allowed in:
Completed- Contract finishedCancelled- Contract cancelledDisputed- Contract under disputeRefunded- Contract refunded
Migration proposals expire after PENDING_MIGRATION_TTL_LEDGERS (defined in ttl module).
All migration operations emit events with the following structure:
client_migration_proposed: (contract_id, current_client, proposed_client, timestamp)client_migration_confirmed: (contract_id, current_client, proposed_client, timestamp)client_migration_finalized: (contract_id, current_client, proposed_client, timestamp)client_migration_cancelled: (contract_id, current_client, proposed_client, timestamp)
- Proposal: Only current client can initiate migration
- Confirmation: Only proposed client can accept migration
- Cancellation: Only current client can cancel migration
- Finalization: No authorization required (public but requires confirmation)
- Unauthorized Takeover: Requires both current and proposed client authorization
- Stale Proposals: TTL-based expiration prevents indefinite pending migrations
- Race Conditions: Atomic finalization prevents partial state updates
- Status Abuse: Migration restricted to appropriate contract states
- Duplicate Migrations: Only one pending migration allowed per contract
All migration operations emit events providing:
- Complete migration timeline
- Participant addresses
- Operation timestamps
- Contract state changes
The implementation includes comprehensive tests covering:
- Migration proposal, confirmation, and finalization flow
- Authorization transfer verification
- Pending state management
- Unauthorized proposal attempts
- Unauthorized confirmation attempts
- Same address migration prevention
- Double proposal prevention
- Status restriction enforcement
- Migration expiration (TTL)
- Contract integrity preservation
- Event emission verification
- Cancellation scenarios
- Migration with funded contracts
- Migration with milestone releases
- Authority transfer validation
// 1. Current client proposes migration
client.request_client_migration(contract_id, new_client_address);
// 2. Check pending migration
let pending = client.get_pending_client_migration(contract_id);
assert!(!pending.proposed_client_confirmed);
// 3. Proposed client confirms migration
client.confirm_client_migration(contract_id);
// 4. Finalize migration (atomic update)
client.finalize_client_migration(contract_id);
// 5. Verify migration completed
let contract = client.get_contract(contract_id);
assert_eq!(contract.client, new_client_address);The implementation uses existing error codes where appropriate:
InvalidStatusTransition- Migration not allowed in current stateUnauthorizedRole- Authorization failuresInvalidParticipant- Same address migrationAlreadyCancelled- Duplicate migration proposalContractNotFound- Missing contract or pending migration
Potential future improvements:
- Migration Delays: Add configurable delay between confirmation and finalization
- Multi-signature: Support for multi-signature client accounts
- Migration Limits: Rate limiting on migration frequency
- Emergency Controls: Admin override capabilities for disputed cases
This implementation addresses all requirements from issue #250: ✅ Secure two-step proposal + confirmation flow ✅ No unauthorized takeover protection ✅ Atomic confirmation with audit trail ✅ Status-based migration restrictions ✅ Comprehensive test coverage ✅ Event emissions for all operations ✅ Documentation and security considerations