Мне нужен список ссылочных номеров, каждый из которых относится к определенной сумме, но когда список достигает большого размера, любые транзакции, связанные с этим списком, вызывают исключение отсутствия газа.
Я пишу это для токена 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 с использованием трюфеля.