CrossChainSaleManager

CrossChainSaleManager Documentation

Overview

The CrossChainSaleManager contract is designed to manage cross-chain staking information and interactions between different chains using the Axelar Network. It ensures secure and seamless communication between multiple blockchain networks for staking and sale management purposes.

Table of Contents

  1. Contract Inheritance

  2. State Variables

  3. Constructor

  4. Modifiers

  5. Functions

    • Public Functions

    • Internal Functions

    • View Functions

Contract Inheritance

The CrossChainSaleManager contract inherits from the following contracts:

  • Ownable: Provides basic authorization control functions.

  • AxelarExecutable: Allows the contract to be executed through the Axelar Network.

  • ICrossChainSaleManager: Interface for the cross-chain sale manager.

State Variables

  • IAxelarGasService public immutable AxelarGasService: Axelar Gas Service contract.

  • address public chef: Address of the chef contract.

  • string public chain: The chain identifier.

  • string[] public allChains: List of all chains added to the contract.

  • mapping(string => bool) private isChainAdded: Mapping to check if a chain is added.

  • mapping(string => address) private crossChainSaleManagers: Mapping of chain identifiers to their respective cross-chain sale manager addresses.

  • uint256 expirationTime: Time duration after which the cross-chain staking info expires (default is 30 days).

  • mapping(address => CrossChainStakingInfo) private crossChainStakingInfos: Mapping of user addresses to their cross-chain staking information.

Constructor

The constructor initializes the contract with the following parameters:

  • address admin_: Address of the contract admin.

  • address gateway_: Address of the Axelar gateway.

  • address gasReceiver_: Address of the Axelar gas receiver.

  • string memory chain_: Identifier of the chain.

  • address chefAddress_: Address of the chef contract.

constructor(
    address admin_,
    address gateway_,
    address gasReceiver_,
    string memory chain_,
    address chefAddress_
) AxelarExecutable(gateway_) {
    AxelarGasService = IAxelarGasService(gasReceiver_);
    chain = chain_;
    chef = chefAddress_;

    allChains.push(chain_);
    isChainAdded[chain_] = true;

    crossChainSaleManagers[chain_] = address(this);

    _transferOwnership(admin_);
}

Modifiers

  • verifyChainAndAddress: Verifies if the chain and address are valid.

  • validChain: Ensures the chain is valid.

modifier verifyChainAndAddress(
    string calldata chain_,
    string calldata address_
) {
    address managerAddress = crossChainSaleManagers[chain_];
    require(managerAddress != address(0), "Zero address");

    address sourceAddress = parseAddress(address_);
    require(sourceAddress != address(0), "Invalid address string");

    require(
        managerAddress == sourceAddress,
        "Not allowed to call this contract"
    );
    _;
}

modifier validChain(string calldata chain_) {
    require(isChainAdded[chain_], "Invalid chain");
    _;
}

Functions

Public Functions

  1. setExpirationTime Sets the expiration time for cross-chain staking info.

    function setExpirationTime(uint256 expirationTime_) external onlyOwner {
        expirationTime = expirationTime_;
    }
  2. setCrossChainSaleManager Sets the address of the cross-chain sale manager for a specific chain.

    function setCrossChainSaleManager(
        string memory chain_,
        address crossChainSaleManagerAddress_
    ) external onlyOwner {
        require(crossChainSaleManagerAddress_ != address(0), "Zero address");
        if (!isChainAdded[chain_]) {
            allChains.push(chain_);
            isChainAdded[chain_] = true;
        }
        crossChainSaleManagers[chain_] = crossChainSaleManagerAddress_;
    
        emit CrossChainSaleManagerAdded(chain_, crossChainSaleManagerAddress_);
    }
  3. removeCrossChainSaleManager Removes the cross-chain sale manager for a specific chain.

    function removeCrossChainSaleManager(
        string calldata chain_
    ) external onlyOwner validChain(chain_) {
        uint256 index = findChainIndex(chain_);
        require(index < allChains.length, "Chain not found");
    
        allChains[index] = allChains[allChains.length - 1];
        allChains.pop();
    
        delete crossChainSaleManagers[chain_];
        isChainAdded[chain_] = false;
    
        emit CrossChainSaleManagerRemoved(chain_);
    }
  4. verifyMultiplierCrossChain Verifies the multiplier for cross-chain staking.

    function verifyMultiplierCrossChain(
        string calldata chain_,
        address account_
    ) external payable validChain(chain_) {
        uint256 amount;
        uint256 currentMultiplier;
    
        (amount, currentMultiplier) = getNativeAmountAndMultiplier(account_);
    
        address managerAddress = crossChainSaleManagers[chain_];
    
        bytes memory payload = abi.encode(account_, amount, currentMultiplier);
        string memory target = Strings.toHexString(
            uint256(uint160(managerAddress)),
            20
        );
    
        if (msg.value > 0) {
            AxelarGasService.payNativeGasForContractCall{value: msg.value}(
                address(this),
                chain_,
                target,
                payload,
                msg.sender
            );
        }
        gateway.callContract(chain_, target, payload);
    }

Internal Functions

  1. _execute Internal function to execute the contract call from the Axelar Network.

    function _execute(
        string calldata sourceChain_,
        string calldata sourceAddress_,
        bytes calldata payload_
    ) internal override verifyChainAndAddress(sourceChain_, sourceAddress_) {
        setCrossChainStakingInfo(sourceChain_, payload_);
    }
  2. setCrossChainStakingInfo Sets the cross-chain staking information.

    function setCrossChainStakingInfo(
        string memory chain_,
        bytes memory payload_
    ) internal {
        require(isChainAdded[chain_], "Invalid chain");
    
        (address account, uint256 amount, uint256 multiplier) = abi.decode(
            payload_,
            (address, uint256, uint256)
        );
    
        require(account != address(0), "Zero address");
        require(multiplier >= 10000000000000, "Invalid multiplier");
    
        CrossChainStakingInfo storage info = crossChainStakingInfos[account];
        ChainDetails storage chainDetails = info.details[chain_];
    
        chainDetails.amount = amount;
        chainDetails.multiplier = multiplier;
        chainDetails.lastUpdate = block.timestamp;
    }

View Functions

  1. getCrossChainSaleManager Returns the address of the cross-chain sale manager for a specific chain.

    function getCrossChainSaleManager(
        string memory chain_
    ) external view returns (address) {
        return crossChainSaleManagers[chain_];
    }
  2. getCrossChainStakingDetails Returns the cross-chain staking details for a user on a specific chain.

    function getCrossChainStakingDetails(
        address account_,
        string calldata chain_
    )
        external
        view
        returns (uint256 amount, uint256 multiplier, uint256 lastUpdate)
    {
        ChainDetails storage details = crossChainStakingInfos[account_].details[
            chain_
        ];
        return (details.amount, details.multiplier, details.lastUpdate);
    }
  3. getNativeAmountAndMultiplier Returns the native staking amount and multiplier for a user.

    function getNativeAmountAndMultiplier(
        address account_
    ) public view returns (uint256, uint256) {
        uint256 amount;
        uint256 currentMultiplier;
    
        if (chef == address(0)) {
            return (0, 10000000000000);
        }
    
        (amount, , , , , , ) = ChefInterface(chef).userInfo(0, account_);
        (, currentMultiplier, ) = ChefInterface(chef).stakingScoreAndMultiplier(
            account_,
            amount
        );
        return (amount, currentMultiplier);
    }
  4. getWeightedAverageMultiplier Returns the weighted average multiplier for a user across all chains.

    function getWeightedAverageMultiplier(
        address account_
    ) external view returns (uint256) {
        if (allChains.length == 1) {
            uint256 nativeMultiplier;
            (, nativeMultiplier) = getNativeAmountAndMultiplier(account_);
            return nativeMultiplier;
        } else {
            uint256 totalAmount = 0;
            uint256 weightedMultiplierSum = 0;
    
            for (uint i = 0; i < allChains.length; i++) {
                ChainDetails storage details = crossChainStakingInfos[account_]
                    .details[allChains[i]];
    
                if (i == 0) {
                    uint256 amount;
                    uint256 multiplier;
                    (amount, multiplier) = getNativeAmountAndMultiplier(
                        account_
                    );
                    totalAmount += amount;
                    weightedMultiplierSum += (amount * multiplier);
                } else {
                    if (block.timestamp - details.lastUpdate > expirationTime) {
                        continue;
                    }
                    totalAmount += details.amount;
                    weightedMultiplierSum += (details.amount *
                        details.multiplier);
                }
            }
    

Last updated