ethereumã³ãã¥ããã£ã¼ã§ãé åã®éä¸ã®ãã¼ã¿ãåé¤ãã¦ãå ¨ä½ãè©°ãããã®ã§ããSolidityã§ã©ããã£ããããã®ã§ããï¼ã£ã¦ãã質åããã£ãã®ã§ãããããã¨èª¿ã¹ã¦ã¿ã¾ããã
çµè«ã¨ãã¦ã¯ãSolidityã§ã¯é åã®è¦ç´ ãåé¤ã§ãã¾ããã
çç±ã¨ãã¦ã¯gas代ãäºæ³ã§ããªãã»ã©è¨ãä¸ããå¯è½æ§ããã£ã¦ãªããªãé£ããã£ã¦ããã®ããããã¾ããã
ãã ãgas代ãç¡è¦ããã°èªåã§ããããå¦çãæ¸ããã¨ã¯ã§ãã¾ãã以éã§ã¯å®éã«å®è£
ããªããç解ããSolidityã§é
åã®è¦ç´ ã®åé¤ãé£ããçç±ã説æãã¦ããã¾ãã
ãªããæ¬è¨äºã§å
¬éãã¦ããã³ã¼ãã¯ãããããªåé¡ãå«ãã§ãã¾ãã®ã§å®æ¡ä»¶ã§ã¯å©ç¨ããªãã§ãã ããã
1.æ®éã«å®è£ ãã¦ã¿ã
åé ã§ãæ¸ãã¾ããããSolidityèªä½ã«ã¯é
åã®è¦ç´ ãåé¤ããfunctionã¯ç¨æããã¦ãã¾ãããã®ã§èªåã§å®è£
ãã¾ãã
ä¸çªåç´ãªã¢ã«ã´ãªãºã ã¨ãã¦ã¯ãåé¤ãããindexããå¾ãã®è¦ç´ ãï¼ã¤ãã¤è©°ãã¦ããã£ã¦ãããã®ã§ãããã³ã¼ãã§æ¸ãã¨æ¬¡ã®éãã§ãã
pragma solidity ^0.4.18; contract PackedArray { uint[] public arrays; function push(uint[] _args) public { arrays = _args; } function remove(uint index) public { require(arrays.length > index); uint[] memory copy = new uint[](arrays.length - 1); uint copyIndex = 0; for(uint i = 0; i < arrays.length; i++) { if(i != index) { copy[copyIndex] = arrays[i]; copyIndex += 1; } } arrays = copy; } }
åé¡ç¹
åé ã§gas代ãç¡è¦ããã°ãããã¨ãã£ãçç±ããã®ã«ã¼ãå¦çã§ãã対象ã¨ããarraysã®è¦ç´ æ°ãå¤ããªãã°ããã ãã«ã¼ãåæ°ãå¢ããã®ã§ãgas代ããã«ã«ãªãã¾ããã
ã¨ãããã¨ã§ã次ã¯ã«ã¼ãã使ããªãæ¹æ³ã§å®è£ ã§ããªããèãã¦ã¿ã¾ãã
2. ã«ã¼ãã使ããã«é åã®è¦ç´ ãåé¤ãã
ã¢ã«ã´ãªãºã
ã¢ã«ã´ãªãºã ã¨ãã¦ã¯åç´ã§ãåé¤ãã対象ã®indexãå¢ã«ãã¦ããã®ååé¨åã¨å¾åé¨åã«åãã¦ã³ãã¼ããã°è¯ãã§ããçµæã¨ãã¦çæãããé åã¯å¯¾è±¡ã®è¦ç´ ãåãé¤ããé åã¨ãªãã¾ãã
Solidityã§ã®åé¡ç¹
solidityã§ä¸è¨ã®ã¢ã«ã´ãªãºã ãå®è£
ãããã¨ããã¨ãé常ã®å½ä»¤ã³ã¼ãï¼é«ã¬ãã«ã³ã¼ãã¨ããã¹ãï¼ï¼ã«ã¯é
åã®è¦ç´ ãã¾ã¨ãã¦ã³ãã¼ãããã®ãåå¨ããªããããassemblyã§å®è£
ããå¿
è¦ãã§ãã¾ããã§ãããassemblyã§å®è£
ãããã¨ãã¦ãopcodeã§æ±ããbyteæ°ãéå£ã¨ãªãã¾ãã
ã¡ã¢ãªä¸orã¹ãã¬ã¼ã¸ä¸ã®ãã¼ã¿ãæä½ãããããä»å使ãopcodeã«ã¯æ¬¡ã®4ã¤ã該å½ããã¨æãã¾ãã
- mload - ã¡ã¢ãªãããã¼ã¿ããã¼ããã
- mstore - ã¡ã¢ãªã«ãã¼ã¿ãæ ¼ç´ãã
- sload - ã¹ãã¬ã¼ã¸ãããã¼ã¿ããã¼ããã
- sstore - ã¹ãã¬ã¼ã¸ã«ãã¼ã¿ãæ ¼ç´ãã
ã¾ãã対象ã¨ãããã¼ã¿ãã¹ãã¬ã¼ã¸ãã¡ã¢ãªãã§å®è³ªã©ã£ã¡ãã®ï¼ã¤ã使ããã¨ã«ãªãã¾ãã
ã§ãããã4ã¤ã®opcodeã¯ãªãã¨ãä¸åº¦ã«æ±ãããã¼ã¿ãµã¤ãºã32byteã¨æ±ºã¾ã£ã¦ãã¾ãã
Solidity Opecodes
ä»åã®ã¢ã«ã´ãªãºã ãå®è£ ããä¸ã§ã®çµ¶å¯¾æ¡ä»¶ã¯ä»»æã®byteæ°ãã³ãã¼ãããã¨ã§ããã©ããããã®ããªãã¨ææ¡ãã¦ããã¨ããä»»æã®byteæ°ãæå®ãã¦ãã¼ã¿ãã³ãã¼ã§ããopcodeããããã¨ãæãåºãã¾ããã以ä¸ã®ï¼ã¤ã該å½ãã¾ãã
- calldatacopy - functionå¼ã³åºãæã«æå®ãããå¼æ°ãã¼ã¿ãã¡ã¢ãªä¸ã«ã³ãã¼ãã
- returndatacopy - call or delegatecall ãªã©ã§å¤é¨å¼ã³åºããããContractããã®æ»ãå¤ãã¡ã¢ãªä¸ã«ã³ãã¼ãã
ä»åã¯ãcalldatacopyã使ããããªã®ã§æ©éå®è£ ãã¦ã¿ã¾ããã
pragma solidity ^0.4.18; contract PackedArray { uint[] public arrays; function set(uint[] _args) public { arrays = _args; } function remove(uint index) public { PackedArray(this).pack(arrays, index); } function pack(uint256[] _arrays, uint256 _deleteIndex) external { uint256 length = _arrays.length; uint256[] memory copy = new uint256[](length - 1); assembly { //find array data pos; let freep := mload(0x40) mstore(0x40, add(freep, 0x20)) calldatacopy(freep, 0x4, 0x20) // array data first 32 byte is length. so slide to array body pos; let arrayDataPos := add(mload(freep), 0x20) let size := mul(0x20, _deleteIndex) // method sig 4byte. calldatacopy(add(copy, 0x20), add(0x04, arrayDataPos), size) let afterpos := add(add(copy, 0x20), size) let alldatasize := mul(0x20, length) let aftersize := sub(alldatasize, add(size, 0x20)) let afterindexPos := add(add(arrayDataPos, size), 0x20) calldatacopy(afterpos, add(0x04, afterindexPos), aftersize) } arrays = copy; } }
åé¡ç¹
callãå¼ã³åºããªãã¨ãããªãé½åä¸ãã¹ãã¬ã¼ã¸ä¸ã®ãã¼ã¿ãå ¨ã¦ã¡ã¢ãªä¸ã«å±éããªãã¨ãããªãããããã®æç¹ã§çµæ§å¤§éã®gas代ãå¿ è¦ã«ãªãã¾ãããªã®ã§ãã¯ããã®å®è£ ã§ãgas代ã®åé¡ãæµ®ä¸ãã¾ãã
ã¾ã¨ã
Solidityã§é
åã®è¦ç´ ãåé¤ããæ©è½ãå®è£
ã§ããªãåå ã¯çµå±ã®ã¨ããgas代ãäºæ¸¬ã§ããªããã¨ã§ããããã®çç±ã¯evmã§ç¨æãããopcodeã«é©åãªãã®ããªãããã§ãã
ç¾ç¶ç¨æããã¦ããopcodeã§é å¼µã£ã¦å®è£
ããã¨ãã¦ãåè¿°ããï¼ã¤ã®æ¹æ³ã®ã©ã¡ããã使ããããªãã®ãç¾ç¶ãªã®ããªãã¨æãã¾ãã
è¦ç´ ã®åé¤ãã©ããã¦ãå¿ è¦ã ï¼ã£ã¦ãªã£ãå ´åã¯ãèªåã§Linked Listãå®è£ ããã®ãgas代åé¡ã®çºçããªãä¸çªç°¡åãªæ¹æ³ãªã®ããããã¾ãããã