我需要有一个参考编号列表,每个编号都与一个特定的数量相关,但是当列表数量很大时,与该列表相关的任何交易都会触发“停电异常”。
我正在为ERC-20令牌编写
我试图将迭代次数限制在参考数字列表上,以尝试减少使用的气体,但这不会影响异常的触发。
我尝试通过注释函数的某些部分来缩小问题的范围,这些部分在理论上会触发异常。
我还尝试过创建键的struct数组而不是字符串数组来映射数量。
完整代码在这里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网络上进行测试。