You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
The Asset Manager handles the custody and transfer of assets across different chains using a hub-and-spoke model. The main chain (hub) contains the central Asset Manager, while each integrated blockchain (spoke) has its own Asset Manager implementation. In this case, ICON is the hub and Stacks is the spoke.
Example Usage
Deposit (from Stacks to ICON):
Alice initiates a transfer of 100 STX to Bob's address on ICON.
The Stacks Asset Manager receives Alice's request, locks 100 STX in its contract, sends an RLP-encoded Deposit message to Stacks xCall, and prepares a DepositRevert message for potential rollback.
If Bob fails to receive 100 STX on ICON, the failure is communicated back through the xCall system. Stacks Asset Manager would receive a failure notification and then process the DepositRevert message, unlocking the 100 STX and returning them to Alice's address.
Withdrawal (from ICON to Stacks):
Bob initiates a withdrawal of 50 STX on ICON, specifying Alice's Stacks address as the recipient.
The ICON Asset Manager receives Bob's request, burns 50 STX from Bob's account, sends an RLP-encoded WithdrawTo message to ICON xCall, and prepares a The Stacks Asset Manager receives this RLP-encoded message from the Stacks xCall contract and decodes it.
WithdrawTo message received from Stacks xCall contract and decoded:
If Alice fails to receive 50 STX on Stacks, the failure is communicated back through the xCall system. The ICON Asset Manager would receive a failure notification and then process the WithdrawRollback, minting 50 STX to Bob's account.
WithdrawRollback message sent to ICON xCall contract:
Implement a handle-call-message function from the CallServiceReceiver trait to process incoming cross-chain messages. This function should:
Verify the sender (only accept from trusted cross-chain protocol)
Decode the incoming message
Route to appropriate handling logic based on message type
;; CallServiceReceiver Trait
(define-traitcall-service-receiver-trait
(
;; Handle the call message received from the source chain;; Only called from the Call Message Service
(handle-call-message ((string-ascii150) (buff1024) (list50 (string-ascii150))) (responsebooluint))
)
)
;; Function: handle-call-message;; Description: Handles incoming cross-chain messages;; Parameters:;; - from: (string-ascii 64) - The source address (usually the main Asset Manager);; - data: (buff 1024) - The message data;; - protocols: (list 10 (string-ascii 64)) - List of protocols used for the message;; Returns: (response bool uint) - OK with true if successful, ERR with error code if failed
(define-public (handle-call-message (from (string-ascii64)) (data (buff1024)) (protocols (list10 (string-ascii64))))
(begin;; Implementation;; 1. Verify the message source and protocols;; 2. Decode the message data;; 3. Route to the appropriate function (deposit, deposit-native, or custom actions)
(oktrue)
)
)
NOTE: In Clarity, when passed as a parameter or stored, a contract principal becomes a non-callable value that can only be used for identification. We can't dynamically dispatch to a contract based on a runtime value nor add new trait implementations dynamically. The contract we're calling must be known at compile-time.
This constraint means any list of contracts a system can interact with, such as tokens supported by the Asset Manager, is fixed when the contract is created. In order to update the Asset Manager token list, both a new Asset Manager contract and a new xCall contract would need to be deployed. This is because the the Asset Manager needs to know about the new token and the xCall contract needs to know to call the new Asset Manager. It's like having to rebuild a whole bookshelf just to add one new book.
Proxy Contract: This would be the main entry point that doesn't change.
Implementation Contract: This contains the actual logic and token list, which can be updated.
Registry Contract: Keeps track of the current implementation contract.
;; Function: deposit;; Description: Handles deposits of tokens from other chains;; Parameters:;; - from: (string-ascii 64) - The source address on the originating chain;; - token: principal - The principal of the token contract to deposit to;; - to: (optional principal) - The destination address on Stacks (if not provided, use a derived address from 'from');; - amount: uint - The amount of tokens to deposit;; Returns: (response bool uint) - OK with true if successful, ERR with error code if failed
(define-public (deposit (from (string-ascii64)) (tokenprincipal) (to (optionalprincipal)) (amountuint))
(begin;; Implementation;; 1. Verify the deposit message from the main Asset Manager;; 2. Mint or unlock the tokens on the Stacks chain;; 3. Transfer the tokens to the destination address
(oktrue)
)
)
;; Function: deposit-native;; Description: Handles deposits of native STX from other chains;; Parameters:;; - from: (string-ascii 64) - The source address on the originating chain;; - to: (optional principal) - The destination address on Stacks (if not provided, use a derived address from 'from');; - amount: uint - The amount of STX to deposit;; Returns: (response bool uint) - OK with true if successful, ERR with error code if failed
(define-public (deposit-native (from (string-ascii64)) (to (optionalprincipal)) (amountuint))
(begin;; Implementation;; 1. Verify the deposit message from the main Asset Manager;; 2. Transfer the locked STX to the destination address
(oktrue)
)
)
Withdrawal
;; Function: withdraw-to;; Description: Withdraws tokens from Stacks to be sent to another chain;; Parameters:;; - token: principal - The principal of the token contract to withdraw;; - to: (string-ascii 64) - The destination address on the target chain;; - amount: uint - The amount of tokens to withdraw;; Returns: (response bool uint) - OK with true if successful, ERR with error code if failed
(define-public (withdraw-to (tokenprincipal) (to (string-ascii64)) (amountuint))
(begin;; Implementation;; 1. Burn or lock the tokens on the Stacks chain;; 2. Prepare the withdrawal message for the main Asset Manager;; 3. Call the cross-chain messaging service to send the withdrawal request
(oktrue)
)
)
;; Function: withdraw-native-to;; Description: Withdraws native STX from Stacks to be sent to another chain;; Parameters:;; - to: (string-ascii 64) - The destination address on the target chain;; - amount: uint - The amount of STX to withdraw;; Returns: (response bool uint) - OK with true if successful, ERR with error code if failed
(define-public (withdraw-native-to (to (string-ascii64)) (amountuint))
(begin;; Implementation;; 1. Lock the STX in the contract;; 2. Prepare the withdrawal message for the main Asset Manager;; 3. Call the cross-chain messaging service to send the withdrawal request
(oktrue)
)
)
Rate Limiting
Implement a configurable rate-limiting system for withdrawals:
Per-token configurable withdrawal limits
Time-based replenishment of withdrawal allowances
Functions to set and update rate limit parameters (owner-only)
Overview
The Asset Manager handles the custody and transfer of assets across different chains using a hub-and-spoke model. The main chain (hub) contains the central Asset Manager, while each integrated blockchain (spoke) has its own Asset Manager implementation. In this case, ICON is the hub and Stacks is the spoke.
Example Usage
Deposit (from Stacks to ICON):
Alice initiates a transfer of 100 STX to Bob's address on ICON.
The Stacks Asset Manager receives Alice's request, locks 100 STX in its contract, sends an RLP-encoded Deposit message to Stacks xCall, and prepares a DepositRevert message for potential rollback.
Deposit message sent to Stacks xCall contract:
DepositRevert message held for potential rollback (not sent):
If Bob fails to receive 100 STX on ICON, the failure is communicated back through the xCall system. Stacks Asset Manager would receive a failure notification and then process the DepositRevert message, unlocking the 100 STX and returning them to Alice's address.
Withdrawal (from ICON to Stacks):
Bob initiates a withdrawal of 50 STX on ICON, specifying Alice's Stacks address as the recipient.
The ICON Asset Manager receives Bob's request, burns 50 STX from Bob's account, sends an RLP-encoded WithdrawTo message to ICON xCall, and prepares a The Stacks Asset Manager receives this RLP-encoded message from the Stacks xCall contract and decodes it.
WithdrawTo message received from Stacks xCall contract and decoded:
If Alice fails to receive 50 STX on Stacks, the failure is communicated back through the xCall system. The ICON Asset Manager would receive a failure notification and then process the WithdrawRollback, minting 50 STX to Bob's account.
WithdrawRollback message sent to ICON xCall contract:
Requirements
Cross-Chain Message Handling
Cross-chain Network Address Representation
Implement cross-chain address representation.
Message Serialization
Implement RLP encoding/decoding for the following cross-chain messages:
handle-call-message
Implement a
handle-call-message
function from theCallServiceReceiver
trait to process incoming cross-chain messages. This function should:Upgradeability
This contract needs to be upgradeable, which is an ongoing barrier for Stacks adoption. However, it should be achievable and we can follow this implementation for reference on how to do it.
In short, there would be 3 contracts:
Proxy Contract: This would be the main entry point that doesn't change.
Implementation Contract: This contains the actual logic and token list, which can be updated.
Registry Contract: Keeps track of the current implementation contract.
Asset Management
Implement a token registry system to manage supported tokens:
Add and remove supported tokens (restricted to contract owner):
Check balances for both STX and SIP-010 tokens:
Deposit
Withdrawal
Rate Limiting
The text was updated successfully, but these errors were encountered: