# Cold Wallet Delegation Standard
## Summary
This RFC introduces a delegation standard to mitigate loss, theft, and unauthorized access to funds stored in cold wallets. The standard maintains the offline nature of cold wallets, allowing cold wallets to delegate ownership of assets to a dedicated hot wallet, thus allowing secure and controlled proof of ownership.
## Motivation: Proof of Ownership
Proof of ownership is one of the more critical yet highly neglected problems in the Solana ecosystem. In its current form, it's highly insecure
- users must connect their cold wallets to unverified websites, or
- transfer their valuable assets to warm wallets
## Goals
This standard aims to remedy this by providing a secure way to delegate assets from cold to hot wallets. This allows users to prove ownership of their assets without risking them by connecting to insecure websites or moving them around.
## Background
> ### Delegation
> **Delegating** an asset from a cold wallet -> hot wallet: The hot wallet is simply *shadowing* as the owner of the asset, and the hot wallet does NOT own any write/transfer rights over this asset, nor does it have the ability to transfer these rights to anyone else. The cold wallet remains the *true* owner of this asset on-chain.
### Actions
Two main actions can be performed using the proposed protocol:
1. Delegation
2. Revoking Delegation
### Delegation Types
1. **Full Wallet Delegation**: The entire wallet gets delegated, including all assets that are owned by the wallet.
2. **Token Delegation**: Tokens having the same mint address can be delegated. This includes fungibles, semi-fungibles and non-fungibles.
## Implementation
PDAs can be used to derive *delegation* accounts for full wallet or token delegation. In each case,
### DelegationAccount
To delegate wallet A to another wallet B, a `DelegationAccount` can be derived using the address of wallet A.
```
#[account]
pub struct DelegateAccount {
// Cold Wallet
pub authority: Pubkey,
pub hot_wallet: Pubkey,
}
where seeds for DelegateAccount:
[
DelegateAccount::PREFIX.as_bytes(),
authority.key().as_ref(),
]
```
### TokenDelegationAccount
In case of token delegation, ie, delegating a token in wallet A with ATA (associated token account) T to wallet B, a `TokenDelegationAccount` can be derived using the address of wallet A and the ATA T.
```rs
#[account]
pub struct DelegateTokenAccount {
pub authority: Pubkey,
pub hot_wallet: Pubkey,
pub token_account: Pubkey,
}
where seeds for DelegateTokenAccount:
[
DelegateTokenAccount::PREFIX.as_bytes(),
authority.key().as_ref(),
token_account.key().as_ref(),
]
```

<!--  -->
### Revoking Delegations
Delegations can be revoked by the authority of the delegation by closing the PDA.
```rs
#[derive(Accounts)]
pub struct RevokeDelegate<'info> {
#[account(mut)]
pub authority: Signer<'info>,
#[account(mut, has_one=authority, close=authority)]
pub delegate_account: Account<'info, DelegateAccount>,
}
#[derive(Accounts)]
pub struct RevokeTokenDelegate<'info> {
pub authority: Signer<'info>,
#[account(mut, has_one=authority, close=authority)]
pub delegate_token_account: Account<'info, DelegateTokenAccount>,
}
```
### Fetching Delegations
This standard would require an SDK for client-side fetching delegated wallets. When a user connects their wallet, the SDK could be used to fetch all the assets that are delegated to the given (connected) hot wallet. Here is a reference implementation of the SDK:
```ts
getUserDelegates = async (hotWallet: PublicKey) => {
const data = await this.delegationProgram.account.DelegateAccount.all([
{
memcmp: {
offset: 8 + 32,
bytes: hotWallet.toBase58(),
},
},
]);
return data;
};
getTokenDelegates = async (hotWallet: PublicKey) => {
const data = await this.delegationProgram.account.DelegateAccount.all([
{
memcmp: {
offset: 8 + 32,
bytes: hotWallet.toBase58(),
},
},
]);
return data;
};
getAllDelegates = async (hotWallet: PublicKey) => {
const userDelegates = await this.getUserDelegates(hot_wallet);
const tokenDelegates = await this.getTokenDelegates(hot_wallet);
return {
userDelegates,
tokenDelegates,
};
};
```
## Some Potential Use-Cases
- Claiming Airdrops
- Claiming Whitelists
- Token-gated mints
- Token-gated games
- DAO Governance
- On-chain reputation
- Verifiable Wallet aggregation
## Ongoing Investigation
* **Supporting Programmable Wallets**: Smart contract wallets like Multisigs are not system accounts and hence the current implementation for the standard can be changed to support PDAs that represent programmable wallets.
* **Allowing tightly scoped rights** to the delegated hot wallet for making transactions on behalf of the cold wallet.
* **Delegation Expiration**: Current implementation requires users to manually revoke a delegation if they no longer want a given hot wallet to be the delegation for a cold wallet. Automatic expiration could be introduced to let users set a dedicated interval, after which the `Delegation/TokenDelegationAccount` will be closed.
## Call For Action
* Requesting **readers** to provide feedback, audit current implementation, and contribute to the codebase.
* Requesting **dapps** to integrate the SDK to provide users with a secure way to prove ownership of their assets.
* Most importantly, requesting all **Wallets** in the ecosystem to provide users an easy way to do the delegation inside the wallets themselves - connecting cold wallets to any website (even one that is created specifically for this standard) goes against the very core principle behind this standard.