Доступ к большому массиву создает исключение исчерпания газа - PullRequest
0 голосов
/ 05 июля 2019

Мне нужен список ссылочных номеров, каждый из которых относится к определенной сумме, но когда список достигает большого размера, любые транзакции, связанные с этим списком, вызывают исключение отсутствия газа.

Я пишу это для токена ERC-20,

Я пытался ограничить количество итераций по списку ссылочных номеров, чтобы попытаться уменьшить используемый газ, но это не влияет на срабатываниеисключение.

Я попытался сузить проблему, комментируя части функции, которые теоретически вызвали бы исключение.

Я также попытался создать массив структур вместо строкового массива ключей.для сопоставления сумм.

Полный код здесь, https://github.com/Abmorano11/GGC-SmartContract

Я объявил следующее как переменные состояния помимо стандартного ERC-20

    string[] private keyRef;
    string[] private tempKeys;

    struct account {
        uint256 balance;
        mapping(string => uint256) tokens;
        string[] keys;
        bool isVerified;
    }

    mapping (address => account) public accInfo;

Это функция «Монетный двор»

function buy(uint256 value, address buyer, string calldata serial) external {
        _totalSupply = _totalSupply.add(value);
        if (accInfo[buyer].tokens[serial] == 0) { //checks if an account owns a serial with an amount
            accInfo[buyer].keys.push(serial);  // Adds it to the account key list
        }
        accInfo[buyer].tokens[serial] = accInfo[buyer].tokens[serial] + value; // Minto Token into Buyer Account Token Mapping
        accInfo[buyer].balance = accInfo[buyer].balance.add(value);     // Updates Buyer Account Balance
    }

Это функция перевода

function  _transfer(address _from, address _to, uint _value) internal {
        uint256 val = _value;                                                                       // Temporary Value Holder
        uint256 length = accInfo[_from].keys.length;                                                // Temporary Length Holder
        keyRef = accInfo[_from].keys;
        for(uint256 index = 0; index < length && index < 10; index++) {
            string memory key = keyRef[index];                                         // Temporary Reference Holder
            if (accInfo[_from].tokens[key] > val && val > 0) {                                     // Check if Token Entry can handle amount
                accInfo[_from].tokens[key] = accInfo[_from].tokens[key] - val;                   // Deduct Temporary Value from Token Entry
                if (accInfo[_to].tokens[key] == 0) {                                                // Check if recipient doesn't have this reference
                    accInfo[_to].keys.push(key);                                                    // Add Serial to account
                }
                accInfo[_to].tokens[key] = accInfo[_to].tokens[key] + val;                          // Add Value to serial
                val = 0;                                                                            // Empty Temporary Value
            }
            if (accInfo[_from].tokens[key] <= val && val > 0) {                                     // Check if Token Entry will be Emptied
                if (accInfo[_to].tokens[key] == 0) {                                                // Check if recipient doesn't have this serial
                    accInfo[_to].keys.push(key);                                                    // Add Serial to account
                }
                accInfo[_to].tokens[key] = accInfo[_to].tokens[key] + accInfo[_from].tokens[key];   // Add Amount to serial
                val = val - accInfo[_from].tokens[key];                                                // Deduct Token Entry from Temporary Value
                delete accInfo[_from].tokens[key];                                                  // Empty Token Entry
                uint256 len = accInfo[_from].keys.length;
                len = len - 1;
                for (uint256 i = 0; i < len; i++) {
                    tempKeys.push(accInfo[_from].keys[i+1]);
                }
                delete accInfo[_from].keys[len];                                                    // Remove last Entry
                accInfo[_from].keys = tempKeys;                                                   // Reduce Array Length
                delete tempKeys;
            }
        }
        delete keyRef;
        uint256 deducted = _value - val;
        accInfo[_from].balance = accInfo[_from].balance - deducted;                                // Subtract amount from the sender
        accInfo[_to].balance = accInfo[_to].balance + deducted;                                    // Add the amount to the recipient
    }

Когда счету принадлежит около 30 различных ссылочных номеров, любойОтветы, направленные на чтение или изменение списка, создали исключение из-за нехватки газа, но функция чеканки по-прежнему выполнялась.

Тестирование проводилось в сети Ganache с использованием трюфеля.

...