比较记忆中的两个阵列,并返回“不在”中。结果
我有一份大合同,我正在将其分成两部分。目的是拥有常见的功能(并将被许多其他合同使用),以分开以提高效率。
这些功能之一比较了阵列“拥有的符号”和“ targetAssets”中的项目。如果“拥有的符号”中的任何项目不在“ targetAssets”中,则会产生“ Sellsymbols”列表。
以下代码正常工作,而“ sellsymbols”被存储为字符串。由于此功能会变得普遍,因此我需要在内存中运行,因此结果不会被不同合同的呼叫混淆。
pragma solidity >0.8.0;
contract compareArrays {
string[] public ownedSymbols = ["A","B","C"];
string[] public targetAssets = ["A","B"];
string[] sellSymbols;
event sellListEvent(string[]);
function sellList(string[] memory _ownedSymbols, string[] memory _targetAssetsList) internal {
sellSymbols = _ownedSymbols;
for (uint256 i = 0; i < _targetAssetsList.length; i++) {
for (uint256 x = 0; x < sellSymbols.length; x++) {
if (
keccak256(abi.encodePacked((sellSymbols[x]))) ==
keccak256(abi.encodePacked((_targetAssetsList[i])))
) {
if (x < sellSymbols.length) {
sellSymbols[x] = sellSymbols[sellSymbols.length - 1];
sellSymbols.pop();
} else {
delete sellSymbols;
}
}
}
}
emit sellListEvent(sellSymbols);
}
function runSellList() public {
sellList(ownedSymbols,targetAssets);
}
}
理想情况下,该功能将使用“ String []内存Sellsymbols”运行,但是这会恢复错误。
pragma solidity >0.8.0;
contract compareArrays {
string[] public ownedSymbols = ["A","B","C"];
string[] public targetAssets = ["A","B"];
event sellListEvent(string[]);
function sellList(string[] memory _ownedSymbols, string[] memory _targetAssetsList) internal {
string[] memory sellSymbols = _ownedSymbols;
for (uint256 i = 0; i < _targetAssetsList.length; i++) {
for (uint256 x = 0; x < sellSymbols.length; x++) {
if (
keccak256(abi.encodePacked((sellSymbols[x]))) ==
keccak256(abi.encodePacked((_targetAssetsList[i])))
) {
if (x < sellSymbols.length) {
sellSymbols[x] = sellSymbols[sellSymbols.length - 1];
sellSymbols.pop();
} else {
delete sellSymbols;
}
}
}
}
emit sellListEvent(sellSymbols);
}
function runSellList() public {
sellList(ownedSymbols,targetAssets);
}
}
错误:
TypeError: Member "pop" is not available in string memory[] memory outside of storage.
--> contracts/sellSymbols.sol:20:25:
|
20 | sellSymbols.pop();
| ^^^^^^^^^^^^^^^
来自我的两个问题:
- 是否有一种方法可以在内存中进行此操作,以便该函数可以很常见(即同时由多个合约使用)?
- 有更好的方法吗?以下运行昂贵,但这是我能够实现它的唯一途径。
最后一条评论 - 我知道这要容易/便宜得多。这不是我愿意考虑的事情,因为我希望这个项目被分散。
I have a large contract and I am in the process of splitting it out into two. The goal is to have the functions that are common (and will be used by many other contracts) to be separated out for efficiency.
One of these functions compares items in arrays "ownedSymbols" and "targetAssets". It produces a list "sellSymbols" if any item in "ownedSymbols" is not in "targetAssets".
The below code works fine while "sellSymbols" is stored as a string. As this function will become common, I need it to run in memory so the results aren't confused by calls from different contracts.
pragma solidity >0.8.0;
contract compareArrays {
string[] public ownedSymbols = ["A","B","C"];
string[] public targetAssets = ["A","B"];
string[] sellSymbols;
event sellListEvent(string[]);
function sellList(string[] memory _ownedSymbols, string[] memory _targetAssetsList) internal {
sellSymbols = _ownedSymbols;
for (uint256 i = 0; i < _targetAssetsList.length; i++) {
for (uint256 x = 0; x < sellSymbols.length; x++) {
if (
keccak256(abi.encodePacked((sellSymbols[x]))) ==
keccak256(abi.encodePacked((_targetAssetsList[i])))
) {
if (x < sellSymbols.length) {
sellSymbols[x] = sellSymbols[sellSymbols.length - 1];
sellSymbols.pop();
} else {
delete sellSymbols;
}
}
}
}
emit sellListEvent(sellSymbols);
}
function runSellList() public {
sellList(ownedSymbols,targetAssets);
}
}
Ideally the function would run with "string[] memory sellSymbols", however this kicks back an error.
pragma solidity >0.8.0;
contract compareArrays {
string[] public ownedSymbols = ["A","B","C"];
string[] public targetAssets = ["A","B"];
event sellListEvent(string[]);
function sellList(string[] memory _ownedSymbols, string[] memory _targetAssetsList) internal {
string[] memory sellSymbols = _ownedSymbols;
for (uint256 i = 0; i < _targetAssetsList.length; i++) {
for (uint256 x = 0; x < sellSymbols.length; x++) {
if (
keccak256(abi.encodePacked((sellSymbols[x]))) ==
keccak256(abi.encodePacked((_targetAssetsList[i])))
) {
if (x < sellSymbols.length) {
sellSymbols[x] = sellSymbols[sellSymbols.length - 1];
sellSymbols.pop();
} else {
delete sellSymbols;
}
}
}
}
emit sellListEvent(sellSymbols);
}
function runSellList() public {
sellList(ownedSymbols,targetAssets);
}
}
The error:
TypeError: Member "pop" is not available in string memory[] memory outside of storage.
--> contracts/sellSymbols.sol:20:25:
|
20 | sellSymbols.pop();
| ^^^^^^^^^^^^^^^
Two questions from me:
- Is there a way to do this in memory so that the function can be common (i.e. used by multiple contracts at the same time)?
- Is there a better way? The below is expensive to run, but it is the only way I have been able to achieve it.
One final comment - I know this would be much easier/cheaper to run off chain. That is not something I am willing to consider as I want this project to be decentralized.
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(1)
如果要保留现有系统,则在此处介绍最好的解决方案: /a>
如果您只关心特定资产的存在或不存在(而不是通过它们列举),那么您想对 真正降低汽油成本的事情就是所谓的“懒惰的评估。”懒惰的评估是当您不立即计算所有结果(例如,通过迭代阵列将所有余额增加50%),而是修改getters,以使它们的返回值反映了操作(例如将内部变量乘以50%并乘以倍增该变量的
GetBalance
的原始结果)。因此,如果是这种情况,您想做的就是使用以下功能:
&lt; pet peeve&gt;
最后,我知道您说您希望这是分散的,但我确实感到这么说的渴望。如果这是一个不需要分散的系统,请不要分散!权力下放非常适合其他人依靠的项目,例如DNS或任何形式的代币。
从您的变量名称来看,这似乎是某种类似于交易机器人的系统。因此,激励措施是您保持其运行的兴趣,因为您是获得好处的人。权力下放化解决的问题(审查制度,利益冲突等)都不适用于您的计划,因为运行它的人会激励其保持运行并保留程序的副本。对于运行它的用户来说,它不需要安全便宜。您不需要银行级保险库即可存储1美元的钞票!
&lt;/pet peeve&gt;
If you want to keep the existing system, the best solution is described here: https://stackoverflow.com/a/49054593/11628256
If all you care about is the presence or absence of a particular asset (and not enumerating through them), what you're going to want to do to really reduce gas costs is something called "lazy evaluation." Lazy evaluation is when instead of computing all results at once (like increasing all balances by 50% by iterating over an array), you modify the getters so that their return value reflects the operation (such as multiplying an internal variable by 50% and multiplying the original result of
getBalance
by that variable).So, if this is the case, what you want to do is use the following function instead:
<pet peeve>
Finally, I know you say you want this to be decentralized, but I really do feel the urge to say this. If this is a system that doesn't need to be decentralized, don't decentralize it! Decentralization is great for projects that other people rely on - for example, DNS or any sort of token.
From your variable names, it seems that this is probably some sort of system similar to a trading bot. Therefore, the incentive is on you to keep it running, as you are the one that gets the benefits. None of the problems that decentralization solves (censorship, conflict of interest, etc...) apply to your program, as the person running it is incentivized to keep it running and keep a copy of the program. It's cheaper for the user running it to not have security they don't need. You don't need a bank-grade vault to store a $1 bill!
</pet peeve>