0

I keep getting this error when trying to compile my code. this same error has occurred at multiple places in my file. The code snippet where the error occurs is as follows:

code:

    pragma solidity ^0.8.0;

import "./ABDKMath64x64.sol";

contract BattleBetting {
    using ABDKMath64x64 for int128;
    using ABDKMath64x64 for uint256;

    enum BattleType { Memecoin, CryptoInfluencer, Sports }

    struct Battle {
        address creator;
        BattleType battleType;
        uint256 minBet;
        uint256 totalBetAmount;
        uint256 startTime;
        uint256 endTime;
        bool isLive;
        bool isFinalized;
        uint256 opponent1Bets;
        uint256 opponent2Bets;
        uint256 opponent1StartValue;
        uint256 opponent2StartValue;
        mapping(address => uint8) opponentChoice;
        string opponent1;  // direct storage of names instead of addresses
        string opponent2;  
        address[] bettors;  // array to keep track of bettors
        mapping(address => uint256) bets;  // mapping to keep track of each user's bet
    }

    uint256 public battleCount;
    mapping(uint256 => Battle) public battles;
    uint256 public constant CREATION_FEE = 5 ether;
    uint256 public constant MINIMUM_LIVE_AMOUNT = 1000 ether;
    uint256 public constant BETTING_FEE_PERCENTAGE = 3; // 0.3% in basis points
    
    int128 public constant P_MIN = 1 << 64; // 1 in 64.64-bit fixed-point
    int128 public constant P_MAX = 100 << 64; // 100 in 64.64-bit fixed-point
    int128 public constant K = 20000000000000000; // 0.02 in 64.64-bit fixed-point
    int128 public constant X0 = 500 << 64; // 500 in 64.64-bit fixed-point

    event BattleCreated(uint256 battleId, address creator, BattleType battleType, string opponent1, string opponent2, uint256 minBet);
    event BetPlaced(uint256 battleId, address bettor, uint256 amount, uint8 opponent);
    event BattleLive(uint256 battleId, uint256 opponent1StartValue, uint256 opponent2StartValue);
    event BattleFinalized(uint256 battleId, address winner);
    event BetRefunded(uint256 battleId, address bettor, uint256 amount);

    function createBattle(BattleType _battleType, string memory _opponent1, string memory _opponent2, uint256 _minBet, uint256 _duration, uint8 _initialOpponentChoice) public payable {
        require(msg.value >= _minBet + CREATION_FEE, "Insufficient funds to create battle.");

        battleCount++;
        Battle storage newBattle = battles[battleCount];
        newBattle.creator = msg.sender;
        newBattle.battleType = _battleType;
        newBattle.opponent1 = _opponent1;
        newBattle.opponent2 = _opponent2;
        newBattle.minBet = _minBet;
        newBattle.totalBetAmount = _minBet;
        newBattle.startTime = block.timestamp;
        newBattle.endTime = block.timestamp + _duration;
        newBattle.opponent1Bets = _initialOpponentChoice == 1 ? _minBet : 0;
        newBattle.opponent2Bets = _initialOpponentChoice == 2 ? _minBet : 0;
        newBattle.bettors.push(msg.sender);
        newBattle.bets[msg.sender] = _minBet;
        newBattle.opponentChoice[msg.sender] = _initialOpponentChoice;

        // Deduct creation fee immediately
        payable(address(this)).transfer(CREATION_FEE);

        emit BattleCreated(battleCount, msg.sender, _battleType, _opponent1, _opponent2, _minBet);
    }

    function placeBet(uint256 _battleId, uint8 _opponentChoice) public payable {
        Battle storage battle = battles[_battleId];
        require(!battle.isFinalized, "Battle is finalized.");
        require(msg.value >= battle.minBet, "Bet amount is below minimum.");

        uint256 newBetPrice = sigmoidCurve(battle.totalBetAmount);
        require(msg.value >= newBetPrice, "Bet amount is below the current price on the bonding curve.");

        uint256 betAmount = msg.value;
        uint256 fee = (betAmount * BETTING_FEE_PERCENTAGE) / 1000; // 0.3% fee
        uint256 betAmountAfterFee = betAmount - fee;

        battle.totalBetAmount += betAmountAfterFee;
        battle.bets[msg.sender] += betAmountAfterFee;
        battle.opponentChoice[msg.sender] = _opponentChoice;
        if (_opponentChoice == 1) {
            battle.opponent1Bets += betAmountAfterFee;
        } else {
            battle.opponent2Bets += betAmountAfterFee;
        }
        battle.bettors.push(msg.sender);

        // Transfer fee to the contract owner
        payable(address(this)).transfer(fee);

        emit BetPlaced(_battleId, msg.sender, betAmountAfterFee, _opponentChoice);

        if (battle.totalBetAmount >= MINIMUM_LIVE_AMOUNT && !battle.isLive) {
            // Fetch the starting values for the opponents when the battle goes live
            uint256 opponent1StartValue = getOpponentValue(battle.battleType, battle.opponent1);
            uint256 opponent2StartValue = getOpponentValue(battle.battleType, battle.opponent2);

            battle.isLive = true;
            battle.opponent1StartValue = opponent1StartValue;
            battle.opponent2StartValue = opponent2StartValue;

            emit BattleLive(_battleId, opponent1StartValue, opponent2StartValue);
        }
    }

    function finalizeBattle(
        uint256 _battleId,
        uint256 _opponent1EndValue,
        uint256 _opponent2EndValue,
        bool _sportsWinner
    ) public {
        Battle storage battle = battles[_battleId];
        require(block.timestamp >= battle.endTime, "Battle duration has not ended yet.");
        require(!battle.isFinalized, "Battle is already finalized.");
        require(battle.isLive, "Battle did not go live.");

        uint256 winnerBetAmount;
        uint256 loserBetAmount;
        address winner;

        if (battle.battleType == BattleType.Memecoin) {
            // Determine winner by percentage change
            uint256 opponent1Change = (_opponent1EndValue * 100) / battle.opponent1StartValue;
            uint256 opponent2Change = (_opponent2EndValue * 100) / battle.opponent2StartValue;
            if (opponent1Change > opponent2Change) {
                winnerBetAmount = battle.opponent1Bets;
                loserBetAmount = battle.opponent2Bets;
                winner = battle.opponent1; //This has a error
            } else {
                winnerBetAmount = battle.opponent2Bets;
                loserBetAmount = battle.opponent1Bets;
                winner = battle.opponent2; // this has a similar error
            }
        } else if (battle.battleType == BattleType.CryptoInfluencer) {
            // Determine winner by absolute change
            uint256 opponent1Change = _opponent1EndValue - battle.opponent1StartValue;
            uint256 opponent2Change = _opponent2EndValue - battle.opponent2StartValue;
            if (opponent1Change > opponent2Change) {
                winnerBetAmount = battle.opponent1Bets;
                loserBetAmount = battle.opponent2Bets;
                winner = battle.opponent1; // This again has a error
            } else {
                winnerBetAmount = battle.opponent2Bets;
                loserBetAmount = battle.opponent1Bets;
                winner = battle.opponent2; //This has the same error
            }
        } else if (battle.battleType == BattleType.Sports) {
            // Determine winner based on API result
            if (_sportsWinner) { // true indicates opponent1 wins, false indicates opponent2 wins
                winnerBetAmount = battle.opponent1Bets;
                loserBetAmount = battle.opponent2Bets;
                winner = battle.opponent1; // error comes here
            } else {
                winnerBetAmount = battle.opponent2Bets;
                loserBetAmount = battle.opponent1Bets;
                winner = battle.opponent2; //  error occur over here
            }
        }

        uint256 totalReward = battle.totalBetAmount;
        uint256 creatorReward = totalReward / 100;
        uint256 bettorsReward = totalReward - creatorReward;

        // Distribute rewards
        payable(battle.creator).transfer(creatorReward);
        for (uint256 i = 0; i < battle.bettors.length; i++) {
            address bettor = battle.bettors[i];
            if (battle.opponentChoice[bettor] == (winner == battle.opponent1 ? 1 : 2)) {
                uint256 bettorShare = (battle.bets[bettor] * bettorsReward) / winnerBetAmount;
                payable(bettor).transfer(bettorShare);
            }
        }

        battle.isFinalized = true;
        emit BattleFinalized(_battleId, winner);
    }

    function refundBets(uint256 _battleId) public {
        Battle storage battle = battles[_battleId];
        require(block.timestamp >= battle.startTime + 60 minutes, "Refund period not reached.");
        require(!battle.isLive, "Battle is live, cannot refund.");

        for (uint256 i = 0; i < battle.bettors.length; i++) {
            address bettor = battle.bettors[i];
            uint256 betAmount = battle.bets[bettor];
            payable(bettor).transfer(betAmount);
            emit BetRefunded(_battleId, bettor, betAmount);
        }

        battle.isFinalized = true;
    }

    // Dummy function to simulate fetching opponent values, to be replaced with actual implementation
    function getOpponentValue(BattleType _battleType, string memory _opponent) internal view returns (uint256) {
        // Placeholder logic, replace with actual value fetching logic
        return uint256(keccak256(abi.encodePacked(_battleType, _opponent))) % 1000;
    }

    // Sigmoid function implementation
    function sigmoidCurve(uint256 x) internal pure returns (uint256) {
        int128 x_fixed = x.fromUInt();
        int128 L = P_MAX.sub(P_MIN);
        int128 exponent = K.mul(x_fixed.sub(X0)).neg();
        int128 numerator = exponent.exp().add(ABDKMath64x64.ONE);
        int128 result = P_MIN.add(L.div(numerator));
        return result.toUInt();
    }
}

Any help would be appreciated over here. Thanking you guys in advance

3
  • I can’t find the definition of battles array in your shared code. Can you add that in your question too? Commented Jun 21 at 23:54
  • Yes sure, let me share the entire code of the contract itself Commented Jun 22 at 4:58
  • 1
    Hi, I have uploaded the entire code here. Please take a look at it once. Commented Jun 22 at 5:06

1 Answer 1

1

The error is due to the assignment of string value to address type, which is in your case two fields/members (i.e., opponent1 and opponent2) of Battle struct.

So, you need to replace their types with address.

Here's the revised code by replacing the type of opponent1 and opponent2 from string to address at all the occurrences:

// SPDX-License-Identifier: MIT
pragma solidity ^0.8.0;

import "./ABDKMath64x64.sol";

contract BattleBetting {
    using ABDKMath64x64 for int128;
    using ABDKMath64x64 for uint256;

    enum BattleType { Memecoin, CryptoInfluencer, Sports }

    struct Battle {
        address creator;
        BattleType battleType;
        uint256 minBet;
        uint256 totalBetAmount;
        uint256 startTime;
        uint256 endTime;
        bool isLive;
        bool isFinalized;
        uint256 opponent1Bets;
        uint256 opponent2Bets;
        uint256 opponent1StartValue;
        uint256 opponent2StartValue;
        mapping(address => uint8) opponentChoice;
        address opponent1;  // direct storage of names instead of addresses
        address opponent2;  
        address[] bettors;  // array to keep track of bettors
        mapping(address => uint256) bets;  // mapping to keep track of each user's bet
    }

    uint256 public battleCount;
    mapping(uint256 => Battle) public battles;
    uint256 public constant CREATION_FEE = 5 ether;
    uint256 public constant MINIMUM_LIVE_AMOUNT = 1000 ether;
    uint256 public constant BETTING_FEE_PERCENTAGE = 3; // 0.3% in basis points
    
    int128 public constant P_MIN = 1 << 64; // 1 in 64.64-bit fixed-point
    int128 public constant P_MAX = 100 << 64; // 100 in 64.64-bit fixed-point
    int128 public constant K = 20000000000000000; // 0.02 in 64.64-bit fixed-point
    int128 public constant X0 = 500 << 64; // 500 in 64.64-bit fixed-point

    event BattleCreated(uint256 battleId, address creator, BattleType battleType, address opponent1, address opponent2, uint256 minBet);
    event BetPlaced(uint256 battleId, address bettor, uint256 amount, uint8 opponent);
    event BattleLive(uint256 battleId, uint256 opponent1StartValue, uint256 opponent2StartValue);
    event BattleFinalized(uint256 battleId, address winner);
    event BetRefunded(uint256 battleId, address bettor, uint256 amount);

    function createBattle(BattleType _battleType, address _opponent1, address _opponent2, uint256 _minBet, uint256 _duration, uint8 _initialOpponentChoice) public payable {
        require(msg.value >= _minBet + CREATION_FEE, "Insufficient funds to create battle.");

        battleCount++;
        Battle storage newBattle = battles[battleCount];
        newBattle.creator = msg.sender;
        newBattle.battleType = _battleType;
        newBattle.opponent1 = _opponent1;
        newBattle.opponent2 = _opponent2;
        newBattle.minBet = _minBet;
        newBattle.totalBetAmount = _minBet;
        newBattle.startTime = block.timestamp;
        newBattle.endTime = block.timestamp + _duration;
        newBattle.opponent1Bets = _initialOpponentChoice == 1 ? _minBet : 0;
        newBattle.opponent2Bets = _initialOpponentChoice == 2 ? _minBet : 0;
        newBattle.bettors.push(msg.sender);
        newBattle.bets[msg.sender] = _minBet;
        newBattle.opponentChoice[msg.sender] = _initialOpponentChoice;

        // Deduct creation fee immediately
        payable(address(this)).transfer(CREATION_FEE);

        emit BattleCreated(battleCount, msg.sender, _battleType, _opponent1, _opponent2, _minBet);
    }

    function placeBet(uint256 _battleId, uint8 _opponentChoice) public payable {
        Battle storage battle = battles[_battleId];
        require(!battle.isFinalized, "Battle is finalized.");
        require(msg.value >= battle.minBet, "Bet amount is below minimum.");

        uint256 newBetPrice = sigmoidCurve(battle.totalBetAmount);
        require(msg.value >= newBetPrice, "Bet amount is below the current price on the bonding curve.");

        uint256 betAmount = msg.value;
        uint256 fee = (betAmount * BETTING_FEE_PERCENTAGE) / 1000; // 0.3% fee
        uint256 betAmountAfterFee = betAmount - fee;

        battle.totalBetAmount += betAmountAfterFee;
        battle.bets[msg.sender] += betAmountAfterFee;
        battle.opponentChoice[msg.sender] = _opponentChoice;
        if (_opponentChoice == 1) {
            battle.opponent1Bets += betAmountAfterFee;
        } else {
            battle.opponent2Bets += betAmountAfterFee;
        }
        battle.bettors.push(msg.sender);

        // Transfer fee to the contract owner
        payable(address(this)).transfer(fee);

        emit BetPlaced(_battleId, msg.sender, betAmountAfterFee, _opponentChoice);

        if (battle.totalBetAmount >= MINIMUM_LIVE_AMOUNT && !battle.isLive) {
            // Fetch the starting values for the opponents when the battle goes live
            uint256 opponent1StartValue = getOpponentValue(battle.battleType, battle.opponent1);
            uint256 opponent2StartValue = getOpponentValue(battle.battleType, battle.opponent2);

            battle.isLive = true;
            battle.opponent1StartValue = opponent1StartValue;
            battle.opponent2StartValue = opponent2StartValue;

            emit BattleLive(_battleId, opponent1StartValue, opponent2StartValue);
        }
    }

    function finalizeBattle(
        uint256 _battleId,
        uint256 _opponent1EndValue,
        uint256 _opponent2EndValue,
        bool _sportsWinner
    ) public {
        Battle storage battle = battles[_battleId];
        require(block.timestamp >= battle.endTime, "Battle duration has not ended yet.");
        require(!battle.isFinalized, "Battle is already finalized.");
        require(battle.isLive, "Battle did not go live.");

        uint256 winnerBetAmount;
        uint256 loserBetAmount;
        address winner;

        if (battle.battleType == BattleType.Memecoin) {
            // Determine winner by percentage change
            uint256 opponent1Change = (_opponent1EndValue * 100) / battle.opponent1StartValue;
            uint256 opponent2Change = (_opponent2EndValue * 100) / battle.opponent2StartValue;
            if (opponent1Change > opponent2Change) {
                winnerBetAmount = battle.opponent1Bets;
                loserBetAmount = battle.opponent2Bets;
                winner = battle.opponent1; //This has a error
            } else {
                winnerBetAmount = battle.opponent2Bets;
                loserBetAmount = battle.opponent1Bets;
                winner = battle.opponent2; // this has a similar error
            }
        } else if (battle.battleType == BattleType.CryptoInfluencer) {
            // Determine winner by absolute change
            uint256 opponent1Change = _opponent1EndValue - battle.opponent1StartValue;
            uint256 opponent2Change = _opponent2EndValue - battle.opponent2StartValue;
            if (opponent1Change > opponent2Change) {
                winnerBetAmount = battle.opponent1Bets;
                loserBetAmount = battle.opponent2Bets;
                winner = battle.opponent1; // This again has a error
            } else {
                winnerBetAmount = battle.opponent2Bets;
                loserBetAmount = battle.opponent1Bets;
                winner = battle.opponent2; //This has the same error
            }
        } else if (battle.battleType == BattleType.Sports) {
            // Determine winner based on API result
            if (_sportsWinner) { // true indicates opponent1 wins, false indicates opponent2 wins
                winnerBetAmount = battle.opponent1Bets;
                loserBetAmount = battle.opponent2Bets;
                winner = battle.opponent1; // error comes here
            } else {
                winnerBetAmount = battle.opponent2Bets;
                loserBetAmount = battle.opponent1Bets;
                winner = battle.opponent2; //  error occur over here
            }
        }

        uint256 totalReward = battle.totalBetAmount;
        uint256 creatorReward = totalReward / 100;
        uint256 bettorsReward = totalReward - creatorReward;

        // Distribute rewards
        payable(battle.creator).transfer(creatorReward);
        for (uint256 i = 0; i < battle.bettors.length; i++) {
            address bettor = battle.bettors[i];
            if (battle.opponentChoice[bettor] == (winner == battle.opponent1 ? 1 : 2)) {
                uint256 bettorShare = (battle.bets[bettor] * bettorsReward) / winnerBetAmount;
                payable(bettor).transfer(bettorShare);
            }
        }

        battle.isFinalized = true;
        emit BattleFinalized(_battleId, winner);
    }

    function refundBets(uint256 _battleId) public {
        Battle storage battle = battles[_battleId];
        require(block.timestamp >= battle.startTime + 60 minutes, "Refund period not reached.");
        require(!battle.isLive, "Battle is live, cannot refund.");

        for (uint256 i = 0; i < battle.bettors.length; i++) {
            address bettor = battle.bettors[i];
            uint256 betAmount = battle.bets[bettor];
            payable(bettor).transfer(betAmount);
            emit BetRefunded(_battleId, bettor, betAmount);
        }

        battle.isFinalized = true;
    }

    // Dummy function to simulate fetching opponent values, to be replaced with actual implementation
    function getOpponentValue(BattleType _battleType, address _opponent) internal pure returns (uint256) {
        // Placeholder logic, replace with actual value fetching logic
        return uint256(keccak256(abi.encodePacked(_battleType, _opponent))) % 1000;
    }

    // Sigmoid function implementation
    function sigmoidCurve(uint256 x) internal pure returns (uint256) {
        int128 x_fixed = x.fromUInt();
        int128 L = P_MAX.sub(P_MIN);
        int128 exponent = K.mul(x_fixed.sub(X0)).neg();
        int128 numerator = exponent.exp().add(ABDKMath64x64.ONE);
        int128 result = P_MIN.add(L.div(numerator));
        return result.toUInt();
    }
}

Still, you would encounter this error though:

CompilerError: Stack too deep when compiling inline assembly: Variable value0 is 1 slot(s) too deep inside the stack.

And, that's because of the presence of too many fields/members in your Battle struct. So, if you remove any of the fields (which is of built-in type i.e., uint256, bool or address), then that error would be gone too.

Here's the code where I commented out the minBet field of the Battle struct and all of its occurrences:

// SPDX-License-Identifier: MIT
pragma solidity ^0.8.0;

import "./ABDKMath64x64.sol";

contract BattleBetting {
    using ABDKMath64x64 for int128;
    using ABDKMath64x64 for uint256;

    enum BattleType { Memecoin, CryptoInfluencer, Sports }

    struct Battle {
        address creator;
        BattleType battleType;
        // uint256 minBet;
        uint256 totalBetAmount;
        uint256 startTime;
        uint256 endTime;
        bool isLive;
        bool isFinalized;
        uint256 opponent1Bets;
        uint256 opponent2Bets;
        uint256 opponent1StartValue;
        uint256 opponent2StartValue;
        mapping(address => uint8) opponentChoice;
        address opponent1;  // direct storage of names instead of addresses
        address opponent2;  
        address[] bettors;  // array to keep track of bettors
        mapping(address => uint256) bets;  // mapping to keep track of each user's bet
    }

    uint256 public battleCount;
    mapping(uint256 => Battle) public battles;
    uint256 public constant CREATION_FEE = 5 ether;
    uint256 public constant MINIMUM_LIVE_AMOUNT = 1000 ether;
    uint256 public constant BETTING_FEE_PERCENTAGE = 3; // 0.3% in basis points
    
    int128 public constant P_MIN = 1 << 64; // 1 in 64.64-bit fixed-point
    int128 public constant P_MAX = 100 << 64; // 100 in 64.64-bit fixed-point
    int128 public constant K = 20000000000000000; // 0.02 in 64.64-bit fixed-point
    int128 public constant X0 = 500 << 64; // 500 in 64.64-bit fixed-point

    event BattleCreated(uint256 battleId, address creator, BattleType battleType, address opponent1, address opponent2, uint256 minBet);
    event BetPlaced(uint256 battleId, address bettor, uint256 amount, uint8 opponent);
    event BattleLive(uint256 battleId, uint256 opponent1StartValue, uint256 opponent2StartValue);
    event BattleFinalized(uint256 battleId, address winner);
    event BetRefunded(uint256 battleId, address bettor, uint256 amount);

    function createBattle(BattleType _battleType, address _opponent1, address _opponent2, uint256 _minBet, uint256 _duration, uint8 _initialOpponentChoice) public payable {
        require(msg.value >= _minBet + CREATION_FEE, "Insufficient funds to create battle.");

        battleCount++;
        Battle storage newBattle = battles[battleCount];
        newBattle.creator = msg.sender;
        newBattle.battleType = _battleType;
        newBattle.opponent1 = _opponent1;
        newBattle.opponent2 = _opponent2;
        // newBattle.minBet = _minBet;
        newBattle.totalBetAmount = _minBet;
        newBattle.startTime = block.timestamp;
        newBattle.endTime = block.timestamp + _duration;
        newBattle.opponent1Bets = _initialOpponentChoice == 1 ? _minBet : 0;
        newBattle.opponent2Bets = _initialOpponentChoice == 2 ? _minBet : 0;
        newBattle.bettors.push(msg.sender);
        newBattle.bets[msg.sender] = _minBet;
        newBattle.opponentChoice[msg.sender] = _initialOpponentChoice;

        // Deduct creation fee immediately
        payable(address(this)).transfer(CREATION_FEE);

        emit BattleCreated(battleCount, msg.sender, _battleType, _opponent1, _opponent2, _minBet);
    }

    function placeBet(uint256 _battleId, uint8 _opponentChoice) public payable {
        Battle storage battle = battles[_battleId];
        require(!battle.isFinalized, "Battle is finalized.");
        // require(msg.value >= battle.minBet, "Bet amount is below minimum.");

        uint256 newBetPrice = sigmoidCurve(battle.totalBetAmount);
        require(msg.value >= newBetPrice, "Bet amount is below the current price on the bonding curve.");

        uint256 betAmount = msg.value;
        uint256 fee = (betAmount * BETTING_FEE_PERCENTAGE) / 1000; // 0.3% fee
        uint256 betAmountAfterFee = betAmount - fee;

        battle.totalBetAmount += betAmountAfterFee;
        battle.bets[msg.sender] += betAmountAfterFee;
        battle.opponentChoice[msg.sender] = _opponentChoice;
        if (_opponentChoice == 1) {
            battle.opponent1Bets += betAmountAfterFee;
        } else {
            battle.opponent2Bets += betAmountAfterFee;
        }
        battle.bettors.push(msg.sender);

        // Transfer fee to the contract owner
        payable(address(this)).transfer(fee);

        emit BetPlaced(_battleId, msg.sender, betAmountAfterFee, _opponentChoice);

        if (battle.totalBetAmount >= MINIMUM_LIVE_AMOUNT && !battle.isLive) {
            // Fetch the starting values for the opponents when the battle goes live
            uint256 opponent1StartValue = getOpponentValue(battle.battleType, battle.opponent1);
            uint256 opponent2StartValue = getOpponentValue(battle.battleType, battle.opponent2);

            battle.isLive = true;
            battle.opponent1StartValue = opponent1StartValue;
            battle.opponent2StartValue = opponent2StartValue;

            emit BattleLive(_battleId, opponent1StartValue, opponent2StartValue);
        }
    }

    function finalizeBattle(
        uint256 _battleId,
        uint256 _opponent1EndValue,
        uint256 _opponent2EndValue,
        bool _sportsWinner
    ) public {
        Battle storage battle = battles[_battleId];
        require(block.timestamp >= battle.endTime, "Battle duration has not ended yet.");
        require(!battle.isFinalized, "Battle is already finalized.");
        require(battle.isLive, "Battle did not go live.");

        uint256 winnerBetAmount;
        uint256 loserBetAmount;
        address winner;

        if (battle.battleType == BattleType.Memecoin) {
            // Determine winner by percentage change
            uint256 opponent1Change = (_opponent1EndValue * 100) / battle.opponent1StartValue;
            uint256 opponent2Change = (_opponent2EndValue * 100) / battle.opponent2StartValue;
            if (opponent1Change > opponent2Change) {
                winnerBetAmount = battle.opponent1Bets;
                loserBetAmount = battle.opponent2Bets;
                winner = battle.opponent1; //This has a error
            } else {
                winnerBetAmount = battle.opponent2Bets;
                loserBetAmount = battle.opponent1Bets;
                winner = battle.opponent2; // this has a similar error
            }
        } else if (battle.battleType == BattleType.CryptoInfluencer) {
            // Determine winner by absolute change
            uint256 opponent1Change = _opponent1EndValue - battle.opponent1StartValue;
            uint256 opponent2Change = _opponent2EndValue - battle.opponent2StartValue;
            if (opponent1Change > opponent2Change) {
                winnerBetAmount = battle.opponent1Bets;
                loserBetAmount = battle.opponent2Bets;
                winner = battle.opponent1; // This again has a error
            } else {
                winnerBetAmount = battle.opponent2Bets;
                loserBetAmount = battle.opponent1Bets;
                winner = battle.opponent2; //This has the same error
            }
        } else if (battle.battleType == BattleType.Sports) {
            // Determine winner based on API result
            if (_sportsWinner) { // true indicates opponent1 wins, false indicates opponent2 wins
                winnerBetAmount = battle.opponent1Bets;
                loserBetAmount = battle.opponent2Bets;
                winner = battle.opponent1; // error comes here
            } else {
                winnerBetAmount = battle.opponent2Bets;
                loserBetAmount = battle.opponent1Bets;
                winner = battle.opponent2; //  error occur over here
            }
        }

        uint256 totalReward = battle.totalBetAmount;
        uint256 creatorReward = totalReward / 100;
        uint256 bettorsReward = totalReward - creatorReward;

        // Distribute rewards
        payable(battle.creator).transfer(creatorReward);
        for (uint256 i = 0; i < battle.bettors.length; i++) {
            address bettor = battle.bettors[i];
            if (battle.opponentChoice[bettor] == (winner == battle.opponent1 ? 1 : 2)) {
                uint256 bettorShare = (battle.bets[bettor] * bettorsReward) / winnerBetAmount;
                payable(bettor).transfer(bettorShare);
            }
        }

        battle.isFinalized = true;
        emit BattleFinalized(_battleId, winner);
    }

    function refundBets(uint256 _battleId) public {
        Battle storage battle = battles[_battleId];
        require(block.timestamp >= battle.startTime + 60 minutes, "Refund period not reached.");
        require(!battle.isLive, "Battle is live, cannot refund.");

        for (uint256 i = 0; i < battle.bettors.length; i++) {
            address bettor = battle.bettors[i];
            uint256 betAmount = battle.bets[bettor];
            payable(bettor).transfer(betAmount);
            emit BetRefunded(_battleId, bettor, betAmount);
        }

        battle.isFinalized = true;
    }

    // Dummy function to simulate fetching opponent values, to be replaced with actual implementation
    function getOpponentValue(BattleType _battleType, address _opponent) internal pure returns (uint256) {
        // Placeholder logic, replace with actual value fetching logic
        return uint256(keccak256(abi.encodePacked(_battleType, _opponent))) % 1000;
    }

    // Sigmoid function implementation
    function sigmoidCurve(uint256 x) internal pure returns (uint256) {
        int128 x_fixed = x.fromUInt();
        int128 L = P_MAX.sub(P_MIN);
        int128 exponent = K.mul(x_fixed.sub(X0)).neg();
        int128 numerator = exponent.exp().add(ABDKMath64x64.ONE);
        int128 result = P_MIN.add(L.div(numerator));
        result.toUInt();
    }
}

This code is getting compiled correctly. So, you can decide to remove one of the fields from the Battle struct accordingly, basically by reconstructing some of the logic to eliminate the need for that particular field in the Battle struct.

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Not the answer you're looking for? Browse other questions tagged or ask your own question.