1/5
_Follow along with this video:_ --- ### Duplicating Stack Items At this point, what we've written will handle call data which pertains to the updateHorseNumber function selector. We need to ask ourselves - _"How are we going to handle if a different selector is passed with our received `call data`?"_ We could do another comparison, but if we haven't jumped anywhere, our stack is empty. We would have to again derive what the call data's function selector is from scratch, implementing another round of `calldataload` and `shr`. There may be a better way... ```js #define macro MAIN() = takes(0) returns(0){ 0x00 calldataload 0xe0 shr // [function_selector] 0xcdfead2e // [0xcdfead2e, function_selector] eq // [true/false] updateJump // [updateHorseNumberProgramCounter, true/false] jumpi // [] updateJump: SET_NUMBER_OF_HORSES() } #define macro SET_NUMBER_OF_HORSES() = takes(0) returns(0){} ``` An op code is available to us which will help us achieve a cleaner and more gas efficient path to our goal, `DUP1` ::image{src='/formal-verification-1/22-dup1/dup1-1.png' style='width: 75%; height: auto;'} `DUP1` simply takes the top item of the stack, copies it and adds both items back to the stack. By executing this op code directly after the first time we accessed the `call data`'s `function selector`, it would keep a copy of this selector for us to access, on the bottom of our stack. How does this look in our code? ```js #define macro MAIN() = takes(0) returns(0){ 0x00 calldataload 0xe0 shr // [function_selector] dup1 // [function_selector, function selector] 0xcdfead2e // [0xcdfead2e, function_selector, function selector] eq // [true/false, function selector] updateJump // [updateHorseNumberProgramCounter, true/false, function selector] jumpi // [function selector] updateJump: SET_NUMBER_OF_HORSES() } #define macro SET_NUMBER_OF_HORSES() = takes(0) returns(0){} ``` I've updated the comments in the code above to visualize how our duplicated `function selector` is carried through each step of execution. We see resultingly that, if we don't jump to `updateJump`, our stack still retains the `function selector` that was passed with the received `call data`. Now that we have access to this function selector again, we're prepared to start handling calls to `readNumberOfHorses()`. Let's look at that in the next lesson!
A comprehensive guide to the DUP1 opcode in Huff. Learn how the DUP1 opcode duplicates the top item on the stack and why it's a valuable tool for function selector checking.
Previous lesson
Previous
Next lesson
Next
Give us feedback
Course Overview
About the course
Assembly
Writing smart contracts using Huff and Yul
Ethereum Virtual Machine OPCodes
Formal verification testing
Smart contract invariant testing
Halmos, Certora, Kontrol
Security researcher
$49,999 - $120,000 (avg. salary)
Smart Contract Auditor
$100,000 - $200,000 (avg. salary)
Guest lecturers:
Josselin Feist
Head of Blockchain at Trail of Bits
Last updated on January 17, 2025
Solidity Developer
Assembly and Formal VerificationDuration: 30min
Duration: 4h 38min
Duration: 3h 57min
Duration: 1h 56min
Course Overview
About the course
Assembly
Writing smart contracts using Huff and Yul
Ethereum Virtual Machine OPCodes
Formal verification testing
Smart contract invariant testing
Halmos, Certora, Kontrol
Security researcher
$49,999 - $120,000 (avg. salary)
Smart Contract Auditor
$100,000 - $200,000 (avg. salary)
Guest lecturers:
Josselin Feist
Head of Blockchain at Trail of Bits
Last updated on January 17, 2025
Testimonials
Read what our students have to say about this course.
Chainlink
Chainlink
Gustavo Gonzalez
Solutions Engineer at OpenZeppelin
Francesco Andreoli
Lead Devrel at Metamask
Albert Hu
DeForm Founding Engineer
Radek
Senior Developer Advocate at Ceramic
Boidushya
WalletConnect
Idris
Developer Relations Engineer at Axelar