Bixia 1994 2021-08-20 00:37:28 阅读数:1,003
J'écris des contrats récemment,Les messages d'erreur suivants sont rencontrés lors de la compilation du contrat,Au début, je n'ai jamais pensé à ce qui s'était mal passé,Écris donc cet article pour enregistrement.
Au début du contrat,Ajouter la ligne suivante,PréciserABIMode de codage:
pragma experimental ABIEncoderV2;
Ce type d'erreur se réfère à:Les tableaux dynamiques imbriqués sont actuellementSolidityNon pris en charge pour le moment.
Mais dans les contrats existants:Par exemple:BaseBoringBatchable.sol
Dansbatch
Fonctions:
function batch(bytes[] calldata calls, bool revertOnFail) external payable returns (bool[] memory successes, bytes[] memory results) { uint n = calls.length; successes = new bool[](n); results = new bytes[](n); for (uint i = 0; i < n; i++) { bytes memory data = calls[i]; (bool success, bytes memory result) = address(this).delegatecall(data); require(success || !revertOnFail, _getRevertMsg(result)); successes[i] = success; results[i] = result; }}function _getRevertMsg(bytes memory data) internal returns(string) { uint len; uint pointer; assembly{ len := mload(data) pointer := add(data, 0x04) } if (len < 68) { return("Transaction reverted silently"); } return abi.decode(pointer, (string));}
Au - dessus de batch
En fonction, Un type est accepté dans son argument de fonction bytes[]
Paramètres pour, Si vous mettez simplement cette fonction dans un contrat pour compiler ,Ça va se produire.:
UnimplementedFeatureError: Nested dynamic arrays not implemented here
Alors,Pourquoibytes[] Est un tableau dynamique imbriqué ?
La raison en est quebytes Le type lui - même est un tableau dynamique ,stringC'est aussi,uint[]C'est aussi.
Alors...bytes[] Est un tableau dynamique imbriqué .
Pour ce qui précède batchFonctions,Lebytes[] Besoin de stocker chaque méthode à appeler calldata. Par exemple, nous appellerons la méthode suivante :
function commitEth( address payable _beneficiary, bool readAndAgreedToMarketParticipationAgreement)
Le nôtre. calldata
Ça devrait être:
abi.encodePacked(address(this).commitEth.selector, uint256(uint160(address(this))), uint256(0x01));=>0x73973fcb000000000000000000000000c351628eb244ec633d5f21fbd6621e1a683b11810000000000000000000000000000000000000000000000000000000000000001
Est utilisé en mémoire bytes[]Pour:
function hack() public payable{ bytes[] memory data = new bytes[](3); bytes momory call_data = abi.encodePacked(address(this).commitEth.selector, uint256(uint160(address(this))), uint256(0x01)); data[0] = call_data; data[1] = call_data; data[2] = call_data; }
Quand trois call_data Placé en mémoire bytes[]Heure, La disposition de la mémoire doit être la suivante: :
0x00 0000000000000000000000000000000000000000000000000000000000000003 // len0x20 0000000000000000000000000000000000000000000000000000000000000080 // loc10x40 00000000000000000000000000000000000000000000000000000000000000e4 // loc20x60 0000000000000000000000000000000000000000000000000000000000000148 // loc30x80 0000000000000000000000000000000000000000000000000000000000000044 // len(part1)0xa0 73973fcb // part10xa4 000000000000000000000000c351628eb244ec633d5f21fbd6621e1a683b1181 // part10xc4 0000000000000000000000000000000000000000000000000000000000000001 // part10xe4 0000000000000000000000000000000000000000000000000000000000000044 // len(part2)0x104 73973fcb // part20x108 000000000000000000000000c351628eb244ec633d5f21fbd6621e1a683b1181 // part20x128 0000000000000000000000000000000000000000000000000000000000000001 // part20x148 0000000000000000000000000000000000000000000000000000000000000044 // len(part3)0x14c 73973fcb // part30x16c 000000000000000000000000c351628eb244ec633d5f21fbd6621e1a683b1181 // part30x18c 0000000000000000000000000000000000000000000000000000000000000001 // part3
Ce n'est pas tout à fait cohérent. , Il a utilisé data[0]=data[1]=data[2]Conditions, Par conséquent, pointez à plusieurs reprises vers le même point de mémoire .
De même pour ce qui précède batch
Fonctions,Laissez - le ici.EVM Stockage dans la fente de , Le contrat doit être conçu comme suit: :
contract Exploit { bytes[] public data; function hack() public payable{ bytes momory call_data = abi.encodePacked(bytes4(0x73973fcb), uint256(uint160(address(this))), uint256(0x01)); data.push(call_data); data.push(call_data); data.push(call_data); }}
Encore trois. call_dataÀdataMoyenne,EtdataInEVM La disposition de stockage doit être :
base_key = 0x0000000000000000000000000000000000000000000000000000000000000000base_value = 3part1_key = keccak256(base_key) + 1part1_value = 0x89part2_key = keccak256(base_key) + 2part2_value = 0x89part3_key = keccak256(base_key) + 3part3_value = 0x89sub_part1_key1 = keccak256(part1_key)sub_part1_value1 = 73973fcb000000000000000000000000c351628eb244ec633d5f21fbd6621e1asub_part1_key2 = sub_part1_key1 + 1sub_part1_value2 = 683b118100000000000000000000000000000000000000000000000000000000sub_part1_key3 = sub_part1_key1 + 2sub_part1_value3 = 0000000100000000000000000000000000000000000000000000000000000000
Demande de recommandation ABIEncoderV2 Matériel connexe ,Merci beaucoup.
Copyright:Cet article est[Bixia 1994]Établi,Veuillez apporter le lien original pour réimprimer,remercier。 https://fra.fheadline.com/2021/08/20210820003707828X.html