Ethereum 我的艺术实验spacecans.com以太坊气体优化
所以我在给一些研究化学进行/r/微量给药,我突然想到我需要做一些artsy区块链的东西。这是两个漂浮在太空中的锡罐,你可以在上面宣传你所谓的垃圾桶或其他东西。它目前正在Rinkeby测试网上运行。你可以用乙醚购买这些锡罐的部分标签,在上面贴上自定义图像,并将其链接到网站 然而,我的智能合约在天然气和安全方面仍然需要一些优化。目前,一笔交易中可以购买的最大面积是32x32个零件中的8x8个零件,因为buyTabs功能显然消耗了太多的汽油。(这是因为块大小限制吗?) 关于天然气优化,有什么建议给坚实的新手吗?谢谢 这是我的智能合约: 以下是网站: pragma solidity>=0.4.22应付地址)参考链接; 结构选项卡{ 应付业主地址; uint256价格;///下次购买的价格 字节32[2]链接URL; bytes32[3]imageUrl; ///用于跨越多个尺寸为X、Y的选项卡的图像 uint8 x;///x索引[0,x-1] uint8x; uint8 y;///y索引[0,y-1] uint8y; } 结构托佩{ 应付业主地址; uint256金额; } 构造函数()公共{ 主席=msg.sender; } 函数uint2str(uint i)内部纯返回(字符串内存){ 如果(i==0)返回“0”; uint j=i; 单位长度; 而(j!=0){ 长度++; j/=10; } 字节内存bstr=新字节(长度); uint k=长度-1; 而(i!=0){ bstr[k--]=字节(uint8(48+i%10)); i/=10; } 返回字符串(bstr); } 函数bytes32ToString(bytes32x)内部纯返回(字符串内存){ 字节内存字节串=新字节(32); uint charCount=0; 对于(uint j=0;j<32;j++){ 字节字符=字节(字节32(uint(x)*2**(8*j)); 如果(字符!=0){ ByteString[charCount]=字符; charCount++; } } bytes memory bytesStringTrimmed=新字节(charCount); 对于(uint j=0;jEthereum 我的艺术实验spacecans.com以太坊气体优化,ethereum,solidity,web3,Ethereum,Solidity,Web3,所以我在给一些研究化学进行/r/微量给药,我突然想到我需要做一些artsy区块链的东西。这是两个漂浮在太空中的锡罐,你可以在上面宣传你所谓的垃圾桶或其他东西。它目前正在Rinkeby测试网上运行。你可以用乙醚购买这些锡罐的部分标签,在上面贴上自定义图像,并将其链接到网站 然而,我的智能合约在天然气和安全方面仍然需要一些优化。目前,一笔交易中可以购买的最大面积是32x32个零件中的8x8个零件,因为buyTabs功能显然消耗了太多的汽油。(这是因为块大小限制吗?) 关于天然气优化,有什么建议给坚实
uint256
而不是uint8
。2.使用映射
而不是数组
。3.避免用于循环。1.uint8在我的选项卡结构中不需要更少的气体,因为它使用更少的存储空间吗?2.我只使用数组,beca使用我迭代它们。3.我设法摆脱了Buytab中的第一个for循环,谢谢!1.请阅读:.2.如果可能,请使用映射。如果必须使用for循环,并且它不支持气体限制,则必须更改算法。
address payable chairperson;
uint8 public constant N = 32;
uint8 public constant M = 32;
uint256 public constant initialTabPrice = 1 finney;
uint256 public constant feePercent = 15;
uint256 public constant referralPercent = 30;
uint256 public constant appreciationPercent = 200;
Tab[N][M] public tabs;
mapping (bytes32 => address payable) referralLinks;
struct Tab {
address payable owner;
uint256 price; /// Price for next purchase
bytes32[2] linkUrl;
bytes32[3] imageUrl;
/// Used for images spanning over multiple tabs with dimensions X,Y
uint8 x; /// x index [0, X-1]
uint8 X;
uint8 y; /// y index [0, Y-1]
uint8 Y;
}
struct ToPay {
address payable owner;
uint256 amount;
}
constructor() public {
chairperson = msg.sender;
}
function uint2str(uint i) internal pure returns (string memory){
if (i == 0) return "0";
uint j = i;
uint length;
while (j != 0){
length++;
j /= 10;
}
bytes memory bstr = new bytes(length);
uint k = length - 1;
while (i != 0){
bstr[k--] = byte(uint8(48 + i % 10));
i /= 10;
}
return string(bstr);
}
function bytes32ToString(bytes32 x) internal pure returns (string memory) {
bytes memory bytesString = new bytes(32);
uint charCount = 0;
for (uint j = 0; j < 32; j++) {
byte char = byte(bytes32(uint(x) * 2 ** (8 * j)));
if (char != 0) {
bytesString[charCount] = char;
charCount++;
}
}
bytes memory bytesStringTrimmed = new bytes(charCount);
for (uint j = 0; j < charCount; j++) {
bytesStringTrimmed[j] = bytesString[j];
}
return string(bytesStringTrimmed);
}
function getTabs(uint8 x1, uint8 y1, uint8 x2, uint8 y2) external view returns(string memory) {
string memory res = "";
for (uint8 yt = y1; yt <= y2; yt++) {
for (uint8 xt = x1; xt <= x2; xt++) {
res = string(abi.encodePacked(res, ",", uint2str(getTabPrice(xt,yt)), ",", bytes32ToString(tabs[xt][yt].linkUrl[0]), bytes32ToString(tabs[xt][yt].linkUrl[1]), ",", bytes32ToString(tabs[xt][yt].imageUrl[0]), bytes32ToString(tabs[xt][yt].imageUrl[1]), bytes32ToString(tabs[xt][yt].imageUrl[2]), "#", uint2str(tabs[xt][yt].x), ".", uint2str(tabs[xt][yt].X), ".", uint2str(tabs[xt][yt].y), ".", uint2str(tabs[xt][yt].Y)));
}
}
return res;
}
function getTabPrice(uint8 x, uint8 y) internal view returns(uint256) {
if (tabs[x][y].price == 0) {
return initialTabPrice;
}
return tabs[x][y].price;
}
function getTabOwner(uint8 x, uint8 y) internal view returns(address payable) {
if (tabs[x][y].price == 0) {
return chairperson;
}
return tabs[x][y].owner;
}
// string calldata linkUrl, string calldata imageUrl, string calldata referral
function buyTabs(uint8[4] calldata z, bytes32[6] calldata s) external payable {
/// z: x1, y1, x2, y2
/// Calculate combined price for asked tabs
uint8 xt;
uint8 yt;
uint256 price = 0;
uint256 tabPrice;
address payable tabOwner;
for (xt = z[0]; xt <= z[2]; xt++) {
for (yt = z[1]; yt <= z[3]; yt++) {
price += getTabPrice(xt,yt);
}
}
/// Check if payment is sufficient
assert(msg.value >= price);
ToPay[1024] memory toPay;
/// Pay previous owner and assign new owner and new price
for (xt = z[0]; xt <= z[2]; xt++) {
for (yt = z[1]; yt <= z[3]; yt++) {
tabPrice = getTabPrice(xt,yt);
tabOwner = getTabOwner(xt,yt);
//tabOwner.transfer((tabPrice * (100-feePercent)) / 100);
for(uint i=0; i<=toPay.length;i++) {
if (toPay[i].amount == 0) {
//toPay[i] = ToPay(tabOwner, (tabPrice * (100-feePercent)) / 100);
toPay[i].owner = tabOwner;
toPay[i].amount = (tabPrice * (100-feePercent)) / 100;
break;
}
if (toPay[i].owner == tabOwner) {
toPay[i].amount += (tabPrice * (100-feePercent)) / 100;
break;
}
}
tabs[xt][yt] = Tab(msg.sender, tabPrice * appreciationPercent / 100, [s[0], s[1]] , [s[2], s[3], s[4]], xt-z[0], z[2]-z[0]+1, yt-z[1], z[3]-z[1]+1);
}
}
for(uint i=0; i<=toPay.length;i++) {
if (toPay[i].amount == 0) {
break;
}
toPay[i].owner.transfer(toPay[i].amount);
}
if (s[5][0] != 0) {
referralLinks[s[5]].transfer(address(this).balance * referralPercent / 100);
}
/// Remaining funds are fees
chairperson.transfer(address(this).balance);
}
function setReferralLink(bytes32 linkName) external {
referralLinks[linkName] = msg.sender;
}
function retrieveLostEther() public {
assert(msg.sender == chairperson);
msg.sender.transfer(address(this).balance);
}