Assembly block

  • Marked by assembly { ... }
  • 
    					pragma solidity ^0.6.1;
    					contract Hello {
    						function SayHi() {
    							assembly {
    							// assembly code here
    							}
    						}
    					}
    					

    Comments

  • Use the // or /* */ to denote comments
  • 
    					assembly {
    						// this is a comment
    						/* this is a multiline 
    						*  comment
    						*/
    					}
    					

    Variables

    • Use the let keyword to declare variables
    • Variable is only visible within the block
    • Variable will be assigned 0 if not initialized
    
    					assembly {
    						let x := 1
    						let y // initialized to 0
    					}
    					// x and y not visible here
    					

    Literals

    • decimal or hexadecimal
    • strings up to 32 characters
    
    					assembly {
    						let a := 2
    						let b := 0x03
    						let c := "hello world"
    					}
    					

    Function

    • Take arguments from stack and put results on stack
    • Can return multiple values: let a, b := f(x)
    
    					function callF(uint input) public pure returns(uint x, uint y) {
    						assembly {
    							function f(val) -> a, b {
    								a := add(val, 1)
    								b := val
    							}
    							x, y := f(input)
    						}
    					}
    					

    If

    • Conditionally execute code
    • No else block
    
    						if eq(value, 0) { 
    							value := 3 
    						}
    					

    Switch

    • Similar to if, but with more branching options
    • Fallback or default case: default
    • No fall through to following cases
    
    					assembly {
    						switch x
    							case 0 { x := 1 }
    							default { x := add(x,1) }
    					}
    					

    Loop

    • Repeat operations
    • break: exit the Loop
    • continue: skip to next iteration
    
    					function lo(uint max) public pure returns(uint result) {
    						assembly {
    							for { let i := 0 } 
    							lt(i, 20)
    							{ i := add(i, 1) } {
    							if lt(i,3) { continue }
    							if gt(i, max) { break }
    							result := add(result,1)
    							}
    						}
    					}
    				

    OpCode

    OpCode (Operation Code) is a machine instruction that specifies the operation to be performed - Wikipedia

    OpCode References

    extcodehash

    • Used in openzeppelin IsContract() utilitity
    • Returns the code hash of a contract
    
    						assembly { codehash := extcodehash(accountAddress) }
    					

    Bitwise Operations

    ### Data Sanity - If you access variables of a type that spans less than 256 bits (e.g. uint64, address, bytes16 or byte), bits not part of the type, may not be `zeroed` - Always clear data before using it ``` uint32 x = f(); assembly { x := and(x, 0xffffffff) /* now use x */ } ```
    ### Two's Complement - Used in EVM - Same arithmetic for signed and unsigned - No negative 0
    ### Signed Functions - Use to process signed data - sdiv(), smod(), slt(), sgt(), sar(), signextend() - Would x be 100 or 99 from the following code? ``` int a = -3; assembly { let x := 100 if lt(a, 0) { x := 99 } } ```

    Gas Fee

    • Fee schedule in Ethereum Yellow Paper
    • Some opcodes are more expensive than others
      • e.g. multiplication costs 5 gas; shift left costs 3 gas
    Image for Ethereum Blockchain mechanism Image Ethereum Modified Merkle-Paricia-Trie systme
    ### Benefits of Inline Assembly - Code could be more gas efficient - Bypass Solidity safety checks - Less code, less gas fee - Some operations only available in assembly

    Lab

    Follow the instructions on the readme file of assembly-loop