├── .gitattributes ├── Images └── binance.jpg ├── LICENSE ├── README.md └── solidity └── contracts ├── GetCodeOfAnotherContract.sol └── sumPureAsm.sol /.gitattributes: -------------------------------------------------------------------------------- 1 | *.sol linguist-language=Solidity 2 | -------------------------------------------------------------------------------- /Images/binance.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/IDouble/Ethereum-Solidity-inline-Assembly/1c261d69090dd514929554fe124121a5b3d5e476/Images/binance.jpg -------------------------------------------------------------------------------- /LICENSE: -------------------------------------------------------------------------------- 1 | MIT License 2 | 3 | Copyright (c) 2019 Alpay Yildirim 4 | 5 | Permission is hereby granted, free of charge, to any person obtaining a copy 6 | of this software and associated documentation files (the "Software"), to deal 7 | in the Software without restriction, including without limitation the rights 8 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 9 | copies of the Software, and to permit persons to whom the Software is 10 | furnished to do so, subject to the following conditions: 11 | 12 | The above copyright notice and this permission notice shall be included in all 13 | copies or substantial portions of the Software. 14 | 15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 16 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 17 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 18 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 19 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 20 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 21 | SOFTWARE. 22 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # 🌐 Ethereum Solidity inline Assembly 🔧 2 | 🌐 A Collection of Notes & Knowledge about Solidity inline Assembly 🔧 3 | 4 | ## What is Solidity inline Assembly ❓ 5 | Solidity defines an assembly language that you can use without Solidity and also as “**inline assembly**” **inside Solidity source code**. 6 | 7 | You can interleave Solidity statements with inline assembly in a language close to the one of the **Ethereum Virtual Machine (EVM)**. 8 | 9 | As the **Ethereum Virtual Machine (EVM) is a stack machine**, it is often hard to address the correct stack slot and provide arguments to opcodes at the correct point on the stack. Solidity’s inline assembly helps you do this, and with other issues that arise when writing manual assembly. 10 | ## GetCode 🔍 11 | ``` 12 | pragma solidity ^0.4.0; 13 | 14 | library GetCode { 15 | function at(address _addr) public view returns (bytes o_code) { 16 | assembly { 17 | // retrieve the size of the code, this needs assembly 18 | let size := extcodesize(_addr) 19 | // allocate output byte array - this could also be done without assembly 20 | // by using o_code = new bytes(size) 21 | o_code := mload(0x40) 22 | // new "memory end" including padding 23 | mstore(0x40, add(o_code, and(add(add(size, 0x20), 0x1f), not(0x1f)))) 24 | // store length in memory 25 | mstore(o_code, size) 26 | // actually retrieve the code, this needs assembly 27 | extcodecopy(_addr, add(o_code, 0x20), 0, size) 28 | } 29 | } 30 | } 31 | ``` 32 | ## sumPureAsm 🔧 33 | ``` 34 | pragma solidity ^0.4.16; 35 | 36 | library VectorSum { 37 | function sumPureAsm(uint[] _data) public view returns (uint o_sum) { 38 | assembly { 39 | // Load the length (first 32 bytes) 40 | let len := mload(_data) 41 | 42 | // Skip over the length field. 43 | // Keep temporary variable so it can be incremented in place. 44 | // NOTE: incrementing _data would result in an unusable 45 | // _data variable after this assembly block 46 | let data := add(_data, 0x20) 47 | 48 | // Iterate until the bound is not met. 49 | for 50 | { let end := add(data, len) } 51 | lt(data, end) 52 | { data := add(data, 0x20) } 53 | { 54 | o_sum := add(o_sum, mload(data)) 55 | } 56 | } 57 | } 58 | } 59 | ``` 60 | 61 | ![Binance Ready to give crypto a try ? buy bitcoin and other cryptocurrencies on binance](Images/binance.jpg) 62 | -------------------------------------------------------------------------------- /solidity/contracts/GetCodeOfAnotherContract.sol: -------------------------------------------------------------------------------- 1 | pragma solidity ^0.4.0; 2 | 3 | library GetCode { 4 | function at(address _addr) public view returns (bytes o_code) { 5 | assembly { 6 | // retrieve the size of the code, this needs assembly 7 | let size := extcodesize(_addr) 8 | // allocate output byte array - this could also be done without assembly 9 | // by using o_code = new bytes(size) 10 | o_code := mload(0x40) 11 | // new "memory end" including padding 12 | mstore(0x40, add(o_code, and(add(add(size, 0x20), 0x1f), not(0x1f)))) 13 | // store length in memory 14 | mstore(o_code, size) 15 | // actually retrieve the code, this needs assembly 16 | extcodecopy(_addr, add(o_code, 0x20), 0, size) 17 | } 18 | } 19 | } -------------------------------------------------------------------------------- /solidity/contracts/sumPureAsm.sol: -------------------------------------------------------------------------------- 1 | pragma solidity ^0.4.16; 2 | 3 | library VectorSum { 4 | // This function is less efficient because the optimizer currently fails to 5 | // remove the bounds checks in array access. 6 | function sumSolidity(uint[] _data) public view returns (uint o_sum) { 7 | for (uint i = 0; i < _data.length; ++i) 8 | o_sum += _data[i]; 9 | } 10 | 11 | // We know that we only access the array in bounds, so we can avoid the check. 12 | // 0x20 needs to be added to an array because the first slot contains the 13 | // array length. 14 | function sumAsm(uint[] _data) public view returns (uint o_sum) { 15 | for (uint i = 0; i < _data.length; ++i) { 16 | assembly { 17 | o_sum := add(o_sum, mload(add(add(_data, 0x20), mul(i, 0x20)))) 18 | } 19 | } 20 | } 21 | 22 | // Same as above, but accomplish the entire code within inline assembly. 23 | function sumPureAsm(uint[] _data) public view returns (uint o_sum) { 24 | assembly { 25 | // Load the length (first 32 bytes) 26 | let len := mload(_data) 27 | 28 | // Skip over the length field. 29 | // 30 | // Keep temporary variable so it can be incremented in place. 31 | // 32 | // NOTE: incrementing _data would result in an unusable 33 | // _data variable after this assembly block 34 | let data := add(_data, 0x20) 35 | 36 | // Iterate until the bound is not met. 37 | for 38 | { let end := add(data, len) } 39 | lt(data, end) 40 | { data := add(data, 0x20) } 41 | { 42 | o_sum := add(o_sum, mload(data)) 43 | } 44 | } 45 | } 46 | } --------------------------------------------------------------------------------