Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Add ApplyPendingBalance, Withdraw and CloseAccount to ConfidentialTransfers Precompile #2033

Merged
merged 7 commits into from
Jan 15, 2025
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
Expand Up @@ -97,4 +97,80 @@
verifiers:
# Verify that the apply pending balance was unsuccessful
- type: eval
expr: APPLY_PENDING_BALANCE_CODE != 0
expr: APPLY_PENDING_BALANCE_CODE != 0

- name: Test applying pending balances on confidential token account via precompile
inputs:
# Setup test account
- cmd: printf "12345678\n" | seid keys add ctprapply
- cmd: printf "12345678\n" | seid keys show -a admin
env: ADMIN_ADDR
- cmd: printf "12345678\n" | seid keys show -a ctprapply
env: TEST_PRECOMPILE_ADDR
- cmd: printf "12345678\n" | seid tx bank send $ADMIN_ADDR $TEST_PRECOMPILE_ADDR 10sei -b block --fees 2000usei --chain-id sei -y --output json | jq -r ".code"
- cmd: printf "12345678\n" | seid tx bank send $ADMIN_ADDR $TEST_PRECOMPILE_ADDR 20000uatom -b block --fees 2000usei --chain-id sei -y --output json | jq -r ".code"

# Initialize confidential token account for denom uatom for ctprapply
- cmd: printf "12345678\n" | seid tx ct init-account uatom --from ctprapply --fees 4000usei --chain-id sei -b block -y --output json | jq -r ".code"
env: INIT_ACCOUNT_CODE

# Deposit to the confidential token account
- cmd: printf "12345678\n" | seid tx ct deposit 10000uatom --from ctprapply --fees 4000usei --chain-id sei -b block -y --output json | jq -r ".code"
env: DEPOSIT_CODE

# Query the initial account state
- cmd: printf "12345678\n" | seid q ct account uatom $TEST_PRECOMPILE_ADDR --decryptor ctprapply --output json
env: INITIAL_ACCOUNT_STATE
- cmd: echo $INITIAL_ACCOUNT_STATE | jq -r ".combined_pending_balance"
env: INITIAL_PENDING_BALANCE
- cmd: echo $(( $(echo $INITIAL_ACCOUNT_STATE | jq -r ".decryptable_available_balance") )) # Convert to integer
env: INITIAL_AVAILABLE_BALANCE

# Apply Pending Balances on the confidential token account via precompile
- cmd: |
printf "12345678\n" | seid tx evm call-contract --from ctprapply --fees=40000usei --gas=2000000 0x0000000000000000000000000000000000001010 -b block "$(printf "12345678\n" | seid q evm ct-apply-pending-balance-payload precompiles/confidentialtransfers/abi.json $TEST_PRECOMPILE_ADDR uatom)" | sed "s/.*: //"
env: TX_HASH
- cmd: sleep 2
# Query the Cosmos tx hash
- cmd: |
curl --location --request GET "localhost:8545/" --header "Content-Type: application/json" --data "{\"jsonrpc\":\"2.0\",\"method\":\"sei_getCosmosTx\",\"params\":[\"$TX_HASH\"],\"id\":788}" | jq -r ".result"
env: COSMOS_TX_HASH

# Query the Cosmos tx result
- cmd: seid q tx $COSMOS_TX_HASH --output json | jq -r ".code"
env: APPLY_PENDING_BALANCE_CODE

# Query the account to verify the new account state
- cmd: printf "12345678\n" | seid q ct account uatom $TEST_PRECOMPILE_ADDR --decryptor ctprapply --output json
env: FINAL_ACCOUNT_STATE
- cmd: echo $FINAL_ACCOUNT_STATE | jq -r ".combined_pending_balance"
env: FINAL_PENDING_BALANCE
- cmd: echo $FINAL_ACCOUNT_STATE | jq -r ".pending_balance_credit_counter"
env: FINAL_PENDING_BALANCE_COUNTER
- cmd: echo $FINAL_ACCOUNT_STATE | jq -r ".decryptable_available_balance"
env: FINAL_AVAILABLE_BALANCE

verifiers:
# Verify that the account exists after the instruction is executed.
- type: eval
expr: INIT_ACCOUNT_CODE == 0 or INIT_ACCOUNT_CODE == 38

# Verify that the deposit was successful
- type: eval
expr: DEPOSIT_CODE == 0

# Verify that the deposit was successful
- type: eval
expr: APPLY_PENDING_BALANCE_CODE == 0

# Verify that the pending balance is now 0.
- type: eval
expr: FINAL_PENDING_BALANCE == 0

# Verify that the pending balance counter is 0
- type: eval
expr: FINAL_PENDING_BALANCE_COUNTER == 0

# Verify that the available balance is the sum of the initial pending balance and initial available balance
- type: eval
expr: INITIAL_AVAILABLE_BALANCE + INITIAL_PENDING_BALANCE == FINAL_AVAILABLE_BALANCE
Original file line number Diff line number Diff line change
Expand Up @@ -86,6 +86,44 @@
- type: eval
expr: WITHDRAW_CODE == 0

# Verify that closing the account was successful
- type: eval
expr: CLOSE_ACCOUNT_CODE == 0

- name: Test closing confidential token account via precompile
inputs:
# Setup test account
- cmd: printf "12345678\n" | seid keys add ctprclose
- cmd: printf "12345678\n" | seid keys show -a admin
env: ADMIN_ADDR
- cmd: printf "12345678\n" | seid keys show -a ctprclose
env: TEST_PRECOMPILE_ADDR
- cmd: printf "12345678\n" | seid tx bank send $ADMIN_ADDR $TEST_PRECOMPILE_ADDR 10sei -b block --fees 2000usei --chain-id sei -y --output json | jq -r ".code"
- cmd: printf "12345678\n" | seid tx bank send $ADMIN_ADDR $TEST_PRECOMPILE_ADDR 20000uatom -b block --fees 2000usei --chain-id sei -y --output json | jq -r ".code"

# Initialize confidential token account for denom uatom for ctprclose
- cmd: printf "12345678\n" | seid tx ct init-account uatom --from ctprclose --fees 4000usei --chain-id sei -b block -y --output json | jq -r ".code"
env: INIT_ACCOUNT_CODE

# Close the confidential token account via precompile
- cmd: |
printf "12345678\n" | seid tx evm call-contract --from ctprclose --fees=40000usei --gas=2000000 0x0000000000000000000000000000000000001010 -b block "$(printf "12345678\n" | seid q evm ct-close-account-payload precompiles/confidentialtransfers/abi.json $TEST_PRECOMPILE_ADDR uatom)" | sed "s/.*: //"
env: TX_HASH
- cmd: sleep 2
# Query the Cosmos tx hash
- cmd: |
curl --location --request GET "localhost:8545/" --header "Content-Type: application/json" --data "{\"jsonrpc\":\"2.0\",\"method\":\"sei_getCosmosTx\",\"params\":[\"$TX_HASH\"],\"id\":788}" | jq -r ".result"
env: COSMOS_TX_HASH

# Query the Cosmos tx result
- cmd: seid q tx $COSMOS_TX_HASH --output json | jq -r ".code"
env: CLOSE_ACCOUNT_CODE

verifiers:
# Verify that the account exists after the instruction is executed.
- type: eval
expr: INIT_ACCOUNT_CODE == 0 or INIT_ACCOUNT_CODE == 38

# Verify that closing the account was successful
- type: eval
expr: CLOSE_ACCOUNT_CODE == 0
Original file line number Diff line number Diff line change
Expand Up @@ -120,4 +120,82 @@
verifiers:
# Verify that the withdraw was unsuccessful due to uninitialized account
- type: eval
expr: WITHDRAW_CODE != 0
expr: WITHDRAW_CODE != 0

- name: Test withdrawing on confidential token account via precompile
inputs:
# Setup test account
- cmd: printf "12345678\n" | seid keys add ctprwithdraw
- cmd: printf "12345678\n" | seid keys show -a admin
env: ADMIN_ADDR
- cmd: printf "12345678\n" | seid keys show -a ctprwithdraw
env: TEST_PRECOMPILE_ADDR
- cmd: printf "12345678\n" | seid tx bank send $ADMIN_ADDR $TEST_PRECOMPILE_ADDR 10sei -b block --fees 2000usei --chain-id sei -y --output json | jq -r ".code"
- cmd: printf "12345678\n" | seid tx bank send $ADMIN_ADDR $TEST_PRECOMPILE_ADDR 20000uatom -b block --fees 2000usei --chain-id sei -y --output json | jq -r ".code"

- cmd: echo 10000
env: WITHDRAW_AMOUNT

# Initialize confidential token account for denom uatom for ctprwithdraw
- cmd: printf "12345678\n" | seid tx ct init-account uatom --from ctprwithdraw --fees 4000usei --chain-id sei -b block -y --output json | jq -r ".code"
env: INIT_ACCOUNT_CODE

# Deposit to the confidential token account
- cmd: printf "12345678\n" | seid tx ct deposit ${WITHDRAW_AMOUNT}uatom --from ctprwithdraw --fees 4000usei --chain-id sei -b block -y --output json | jq -r ".code"
env: DEPOSIT_CODE

- cmd: printf "12345678\n" | seid tx ct apply-pending-balance uatom --from ctprwithdraw --fees 4000usei --chain-id sei -b block -y --output json | jq -r ".code"
env: APPLY_PENDING_BALANCE_CODE

# Query the initial account state
- cmd: printf "12345678\n" | seid q ct account uatom $TEST_PRECOMPILE_ADDR --decryptor ctprwithdraw --output json
env: INITIAL_ACCOUNT_STATE
- cmd: echo $INITIAL_ACCOUNT_STATE | jq -r ".combined_pending_balance"
env: INITIAL_PENDING_BALANCE
- cmd: echo $(( $(echo $INITIAL_ACCOUNT_STATE | jq -r ".decryptable_available_balance") )) # Convert to integer
env: INITIAL_AVAILABLE_BALANCE

# Withdraw from the confidential token account via precompile
- cmd: |
printf "12345678\n" | seid tx evm call-contract --from ctprwithdraw --fees=40000usei --gas=2000000 0x0000000000000000000000000000000000001010 -b block "$(printf "12345678\n" | seid q evm ct-withdraw-payload precompiles/confidentialtransfers/abi.json $TEST_PRECOMPILE_ADDR ${WITHDRAW_AMOUNT}uatom)" | sed "s/.*: //"
env: TX_HASH
- cmd: sleep 2
# Query the Cosmos tx hash
- cmd: |
curl --location --request GET "localhost:8545/" --header "Content-Type: application/json" --data "{\"jsonrpc\":\"2.0\",\"method\":\"sei_getCosmosTx\",\"params\":[\"$TX_HASH\"],\"id\":788}" | jq -r ".result"
env: COSMOS_TX_HASH

# Query the Cosmos tx result
- cmd: seid q tx $COSMOS_TX_HASH --output json | jq -r ".code"
env: WITHDRAW_CODE

# Query the account to verify the new account state
- cmd: printf "12345678\n" | seid q ct account uatom $TEST_PRECOMPILE_ADDR --decryptor ctprwithdraw --output json
env: FINAL_ACCOUNT_STATE
- cmd: echo $FINAL_ACCOUNT_STATE | jq -r ".combined_pending_balance"
env: FINAL_PENDING_BALANCE
- cmd: echo $FINAL_ACCOUNT_STATE | jq -r ".pending_balance_credit_counter"
env: FINAL_PENDING_BALANCE_COUNTER
- cmd: echo $FINAL_ACCOUNT_STATE | jq -r ".decryptable_available_balance"
env: FINAL_AVAILABLE_BALANCE

verifiers:
# Verify that the account exists after the instruction is executed.
- type: eval
expr: INIT_ACCOUNT_CODE == 0 or INIT_ACCOUNT_CODE == 38

# Verify that the deposit was successful
- type: eval
expr: DEPOSIT_CODE == 0

# Verify that the apply balances operation was successful
- type: eval
expr: APPLY_PENDING_BALANCE_CODE == 0

# Verify that the withdraw was successful
- type: eval
expr: WITHDRAW_CODE == 0

# Verify that the available balance is the difference between the initial pending balance and withdraw amount
- type: eval
expr: INITIAL_AVAILABLE_BALANCE - WITHDRAW_AMOUNT == FINAL_AVAILABLE_BALANCE
3 changes: 3 additions & 0 deletions precompiles/common/expected_keepers.go
Original file line number Diff line number Diff line change
Expand Up @@ -132,7 +132,10 @@ type ChannelKeeper interface {
}

type ConfidentialTransfersKeeper interface {
ApplyPendingBalance(context.Context, *cttypes.MsgApplyPendingBalance) (*cttypes.MsgApplyPendingBalanceResponse, error)
Deposit(context.Context, *cttypes.MsgDeposit) (*cttypes.MsgDepositResponse, error)
InitializeAccount(context.Context, *cttypes.MsgInitializeAccount) (*cttypes.MsgInitializeAccountResponse, error)
Transfer(goCtx context.Context, req *cttypes.MsgTransfer) (*cttypes.MsgTransferResponse, error)
Withdraw(goCtx context.Context, req *cttypes.MsgWithdraw) (*cttypes.MsgWithdrawResponse, error)
CloseAccount(goCtx context.Context, req *cttypes.MsgCloseAccount) (*cttypes.MsgCloseAccountResponse, error)
}
22 changes: 22 additions & 0 deletions precompiles/confidentialtransfers/CT.sol
Original file line number Diff line number Diff line change
Expand Up @@ -27,6 +27,7 @@ interface ICT {
bytes toAmountLo,
bytes toAmountHi,
bytes remainingBalance,
string decryptableBalance,
bytes proofs
) external returns (bool success);

Expand All @@ -38,6 +39,7 @@ interface ICT {
bytes toAmountLo,
bytes toAmountHi,
bytes remainingBalance,
string decryptableBalance,
bytes proofs,
Auditor[] auditors
) external returns (bool success);
Expand All @@ -57,4 +59,24 @@ interface ICT {
string denom,
uint64 amount
) external returns (bool success);

function applyPendingBalance(
string denom,
string decryptableBalance,
uint32 pendingBalanceCreditCounter,
bytes availableBalance,
) external returns (bool success);

function withdraw(
string denom,
uint256 amount,
string decryptableBalance,
bytes remainingBalanceCommitment,
bytes proofs
) external returns (bool success);

function closeAccount(
string denom,
bytes proofs
) external returns (bool success);
}
2 changes: 1 addition & 1 deletion precompiles/confidentialtransfers/abi.json
Original file line number Diff line number Diff line change
@@ -1 +1 @@
[{"inputs":[{"internalType":"string","name":"toAddress","type":"string"},{"internalType":"string","name":"denom","type":"string"},{"internalType":"bytes","name":"fromAmountLo","type":"bytes"},{"internalType":"bytes","name":"fromAmountHi","type":"bytes"},{"internalType":"bytes","name":"toAmountLo","type":"bytes"},{"internalType":"bytes","name":"toAmountHi","type":"bytes"},{"internalType":"bytes","name":"remainingBalance","type":"bytes"},{"internalType":"string","name":"decryptableAvailableBalance","type":"string"},{"internalType":"bytes","name":"proofs","type":"bytes"}],"name":"transfer","outputs":[{"internalType":"bool","name":"success","type":"bool"}],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"string","name":"toAddress","type":"string"},{"internalType":"string","name":"denom","type":"string"},{"internalType":"bytes","name":"fromAmountLo","type":"bytes"},{"internalType":"bytes","name":"fromAmountHi","type":"bytes"},{"internalType":"bytes","name":"toAmountLo","type":"bytes"},{"internalType":"bytes","name":"toAmountHi","type":"bytes"},{"internalType":"bytes","name":"remainingBalance","type":"bytes"},{"internalType":"string","name":"decryptableAvailableBalance","type":"string"},{"internalType":"bytes","name":"proofs","type":"bytes"},{"internalType":"struct Auditor[]","name":"auditors","type":"tuple[]","components":[{"internalType":"string","name":"auditorAddress","type":"string"},{"internalType":"bytes","name":"encryptedTransferAmountLo","type":"bytes"},{"internalType":"bytes","name":"encryptedTransferAmountHi","type":"bytes"},{"internalType":"bytes","name":"transferAmountLoValidityProof","type":"bytes"},{"internalType":"bytes","name":"transferAmountHiValidityProof","type":"bytes"},{"internalType":"bytes","name":"transferAmountLoEqualityProof","type":"bytes"},{"internalType":"bytes","name":"transferAmountHiEqualityProof","type":"bytes"}]}],"name":"transferWithAuditors","outputs":[{"internalType":"bool","name":"success","type":"bool"}],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"string","name":"fromAddress","type":"string"},{"internalType":"string","name":"denom","type":"string"},{"internalType":"bytes","name":"publicKey","type":"bytes"},{"internalType":"string","name":"decryptableBalance","type":"string"},{"internalType":"bytes","name":"pendingBalanceLo","type":"bytes"},{"internalType":"bytes","name":"pendingBalanceHi","type":"bytes"},{"internalType":"bytes","name":"availableBalance","type":"bytes"},{"internalType":"bytes","name":"proofs","type":"bytes"}],"name":"initializeAccount","outputs":[{"internalType":"bool","name":"success","type":"bool"}],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"string","name":"denom","type":"string"},{"internalType":"uint64","name":"amount","type":"uint64"}],"name":"deposit","outputs":[{"internalType":"bool","name":"success","type":"bool"}],"stateMutability":"nonpayable","type":"function"}]
[{"inputs":[{"internalType":"string","name":"fromAddress","type":"string"},{"internalType":"string","name":"denom","type":"string"},{"internalType":"bytes","name":"publicKey","type":"bytes"},{"internalType":"string","name":"decryptableBalance","type":"string"},{"internalType":"bytes","name":"pendingBalanceLo","type":"bytes"},{"internalType":"bytes","name":"pendingBalanceHi","type":"bytes"},{"internalType":"bytes","name":"availableBalance","type":"bytes"},{"internalType":"bytes","name":"proofs","type":"bytes"}],"name":"initializeAccount","outputs":[{"internalType":"bool","name":"success","type":"bool"}],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"string","name":"toAddress","type":"string"},{"internalType":"string","name":"denom","type":"string"},{"internalType":"bytes","name":"fromAmountLo","type":"bytes"},{"internalType":"bytes","name":"fromAmountHi","type":"bytes"},{"internalType":"bytes","name":"toAmountLo","type":"bytes"},{"internalType":"bytes","name":"toAmountHi","type":"bytes"},{"internalType":"bytes","name":"remainingBalance","type":"bytes"},{"internalType":"string","name":"decryptableBalance","type":"string"},{"internalType":"bytes","name":"proofs","type":"bytes"}],"name":"transfer","outputs":[{"internalType":"bool","name":"success","type":"bool"}],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"string","name":"toAddress","type":"string"},{"internalType":"string","name":"denom","type":"string"},{"internalType":"bytes","name":"fromAmountLo","type":"bytes"},{"internalType":"bytes","name":"fromAmountHi","type":"bytes"},{"internalType":"bytes","name":"toAmountLo","type":"bytes"},{"internalType":"bytes","name":"toAmountHi","type":"bytes"},{"internalType":"bytes","name":"remainingBalance","type":"bytes"},{"internalType":"string","name":"decryptableBalance","type":"string"},{"internalType":"bytes","name":"proofs","type":"bytes"},{"components":[{"internalType":"string","name":"auditorAddress","type":"string"},{"internalType":"bytes","name":"encryptedTransferAmountLo","type":"bytes"},{"internalType":"bytes","name":"encryptedTransferAmountHi","type":"bytes"},{"internalType":"bytes","name":"transferAmountLoValidityProof","type":"bytes"},{"internalType":"bytes","name":"transferAmountHiValidityProof","type":"bytes"},{"internalType":"bytes","name":"transferAmountLoEqualityProof","type":"bytes"},{"internalType":"bytes","name":"transferAmountHiEqualityProof","type":"bytes"}],"internalType":"struct ICT.Auditor[]","name":"auditors","type":"tuple[]"}],"name":"transferWithAuditors","outputs":[{"internalType":"bool","name":"success","type":"bool"}],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"string","name":"denom","type":"string"},{"internalType":"uint64","name":"amount","type":"uint64"}],"name":"deposit","outputs":[{"internalType":"bool","name":"success","type":"bool"}],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"string","name":"denom","type":"string"},{"internalType":"string","name":"decryptableBalance","type":"string"},{"internalType":"uint32","name":"pendingBalanceCreditCounter","type":"uint32"},{"internalType":"bytes","name":"availableBalance","type":"bytes"}],"name":"applyPendingBalance","outputs":[{"internalType":"bool","name":"success","type":"bool"}],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"string","name":"denom","type":"string"},{"internalType":"uint256","name":"amount","type":"uint256"},{"internalType":"string","name":"decryptableBalance","type":"string"},{"internalType":"bytes","name":"remainingBalanceCommitment","type":"bytes"},{"internalType":"bytes","name":"proofs","type":"bytes"}],"name":"withdraw","outputs":[{"internalType":"bool","name":"success","type":"bool"}],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"string","name":"denom","type":"string"},{"internalType":"bytes","name":"proofs","type":"bytes"}],"name":"closeAccount","outputs":[{"internalType":"bool","name":"success","type":"bool"}],"stateMutability":"nonpayable","type":"function"}]
Loading
Loading