Concordium / concordium-rust-smart-contracts

Libraries and tools for writing and testing smart contracts on Concordium
https://docs.rs/concordium-std/latest/concordium_std/
Mozilla Public License 2.0
57 stars 35 forks source link

Chaperone Smart Contract (Smart Contract Wallet Standard) #412

Closed DOBEN closed 6 months ago

DOBEN commented 7 months ago

Executive Summary: Until now, users have to go through KYC to generate an account on Concordium. This new standard, takes away the identified pain points collected from the community associated with the account creation on-boarding flow on Concordium. In addition, it takes away the need to acquire CCD to pay for transaction fees when submitting ‘transfer’ transactions on-chain. The smart contract wallet standard contains a smart contract that keeps track/assigns every cis2Token/nativeCurrency unit that it holds on its address to a corresponding PublicKey (users). This allows users to hold and transfer tokens/currency (we can display it in the wallets as such that the wallet holds the token even if its balance is technically held by the smart contract) without having to submit transactions on chain from their wallet (only generate signatures from their wallet).

Cis2Tokens/nativeCurrency can be deposited into the chaperone smart contract wallet where it needs to be specified to which PublicKey the deposit should be assigned to. Every unit of token/currency in the contract is solely controlled by the PublicKey (user) and can only be moved when provided a valid signature from that public key which will assign/transfer/withdraw the user’s balance to some new accounts (internal or external).

Requirement The goal is to simplify the account creation on-boarding flow on Concordium allowing for CIS5 smart contract wallets being supported as first-class citizens on Concordium.

Technical Overview We use PublicKeyEd25519 and SignatureEd25519 which are often shorten to PublicKey and Signature in the following paragraphs. The three main components are:

Component breakdown

Smart contract reference implementation

The smart contract has two deposit functions (emit Deposit event):

- depositNativeCurrency(beneficiary: PublicKeyEd25519)
- depositCis2Token(params: OnReceivingCis2Params): The `OnReceivingCis2Params` includes a data field which will encode a `beneficiary: PublicKeyEd25519`.This deposit function is meant to be called through the hook mechanism in the CIS2 token contracts.
OnReceivingCis2Params {
                token_id,
                amount,
                from,
                data,
}

If a use case wants to airdrop tokens to a beneficiary (no native account) in one transaction. The CIS2 token would have to have a mint function that calls this smart contract wallet depositCis2Token function via a hook mechanism.

The smart contract has two withdraw functions which will transfer tokens/currency out of this contract to regular nativeAccounts/smartContracts (emit Withdraw event):

- withdrawNativeCurrency(signer: PublicKey, signature: Signature, expiryTime: TimeStamp, nonce: u64,  serviceFee: CCDAmount, serviceFeeRecipient: Address, from: PublicKey, to: Address, amount: CCDAmount)
- withdrawCis2Token(signer: PublicKey, signature: Signature, expiryTime: TimeStamp, nonce: u64,  serviceFee: CCDAmount, serviceFeeRecipient: Address, from: PublicKey, to: Address, tokenAmount: tokenAmount, tokenId: TokenId, contractAddress: ContractAddress): 
These endpoints check if a valid signature is provided. It transfers the `serviceFee` to the `serviceFeeRecipient`.

The smart contract has two internal transfer functions to assign a new PublicKey within the smart contract wallet. The tokens/currency will not move away from the smart contract wallet balance, merely the accounting in the smart contract wallet is changed of who owns what (emit Transfer event):

- internalCis2TokenTransfer(signer: PublicKey, signature: Signature,  expiryTime: TimeStamp, nonce: u64, serviceFee: TokenAmount, serviceFeeRecipient: Address, from: PublicKey, to: PublicKey, amount: TokenAmount, tokenId: ContractTokenId, tokenAddress: ContractAddress) : This endpoint checks if a valid signature is provided. It transfers the `serviceFee` to the  `serviceFeeRecipient`.
- internalNativeCurrencyTransfer(signer: PublicKey, signature: Signature,  expiryTime: TimeStamp, nonce: u64, serviceFee: TokenAmount, serviceFeeRecipient: Address, from: PublicKey, to: PublicKey, amount: Amount) : This endpoint checks if a valid signature is provided. It transfers the `serviceFee` to the `serviceFeeRecipient`.

The smart contract exposes associated balanceOf() functions.

Additional notes:

CIS5 standard proposal document

The contract exposes the supports function from the CIS0 standard. The wallets will check if a contract supports CIS5 before displaying the token balances based on this standard meaningfully. A new proposal CIS5 will be added: https://github.com/Concordium/concordium-update-proposals/pull/60

Adjustments in the browser wallet + mobile wallets

Note about which use cases we support: